<template>
  <div class="wy-grid frame" :style="{ 'user-select': userSelect }">
    <div class="top-card-box" v-if="!$srv.utils.noValue(funName)">
      <o-card-box position="top" :width="150" :height="30">
        <span class="top-card-box-title">
          <span>{{ $srv.getI18nBySrv(funName) }}</span>
        </span>
      </o-card-box>
    </div>
    <div class="mask-container" v-if="isMask"></div>
    <div class="none-container" v-if="nonePermission">
      {{ $srv.getI18nByPath('others.noPermissions') }}···
    </div>
    <div :class="['wy-grid-cover', 'layout' + layoutMode]">
      <Split
        :style="collapseStyle"
        v-model="searchControl.split"
        :mode="searchControl.modeStyle"
        min="0"
        max="0"
      >
        <div class="grid-query" :slot="searchControl.formPosition">
          <div v-if="gridHead.qbeSearch">
            <oBaseForm
              @submit="doSimpleSearch"
              :mode="1"
              @compBoxInfo="regCompItem($event, 'queryByExample')"
            ></oBaseForm>
          </div>
          <div v-if="gridHead.bancodeScan">
            <cBarcodeScan
              :compBoxInfo="GT_compBoxInfo"
              :parentCommand="GT_editor"
            />
          </div>
        </div>
        <div class="grid-content" :slot="searchControl.gridPosition">
          <gridFlowchart
            v-if="$srv.getx(config, 'tableGraphMode', false)"
            v-show="!displayModel"
            :localData="localData"
            :compBoxInfo="GT_compBoxInfo"
            :tableCfg="_config"
            @switch-model="switchModel"
            @on-row-change="rowEditChange"
          ></gridFlowchart>
          <vxe-grid
            v-show="displayModel"
            ref="xGrid"
            auto-resize
            height="auto"
            header-align="center"
            border="outer"
            stripe
            :id="gridID"
            :highlight-current-row="true"
            :row-config="{
              isCurrent: true,
              useKey: false
            }"
            :menu-config="contextMenu"
            :import-config="importConfig"
            :export-config="exportConfig"
            :seq-config="{ startIndex: seqStartIndex }"
            :mouse-config="{ selected: true }"
            :keyboard-config="{ isEdit: true }"
            :sort-config="sortConfig"
            :filter-config="filterConfig"
            :toolbar-config="{
              ...defaultToolbar,
              custom: {
                showFooter: false,
                icon: 'wy-icon wy-lieshezhi'
              },
              slots: {
                buttons: 'toolbar_buttons'
              }
            }"
            :pager-config="pagerConfig"
            :edit-config="editConfig"
            :column-config="{
              useKey: true,
              isCurrent: true,
              isHover: true
            }"
            :custom-config="customConfig"
            :scroll-y="{ gt: 80 }"
            :loading="loading"
            :data="localData"
            :show-header="tableStyle.showHeader"
            :show-footer="isShowFooter"
            :footer-method="footerMethod"
            :columns="tableColumns"
            :edit-rules="validRules"
            :cell-style="cellStyle"
            :row-style="rowStyle"
            :empty-render="{ name: 'notData' }"
            :keep-source="true"
            :checkbox-config="{ range: true }"
            @current-change="handleCurrentRowChange"
            @cell-click="handleCellClick"
            @cell-dblclick="handleCellDBLClick"
            @keydown="listenKeyDown"
            @edit-closed="listenBlur"
            @edit-actived="listenFocus"
            @checkbox-change="checkboxChange"
            @checkbox-all="checkboxChange"
            @menu-click="handleContextMenuClick"
            @page-change="pageChange"
            @sort-change="sortChange"
            @filter-change="filterChange"
          >
            <div class="charts" slot="top" v-if="!isEmpty(charts)" ref="chart">
              <template v-for="(group, key, idx) in charts">
                <div class="chart-group" :key="idx" v-if="group[0]['isShow']">
                  <template v-if="group['length'] === 1">
                    <div :class="['chart-cover']">
                      <oBaseChart
                        :config="group[0]"
                        :localData="localData"
                        identification="grid"
                        :title="funName"
                      ></oBaseChart>
                    </div>
                  </template>
                  <template v-else-if="group['length'] === 2">
                    <Split v-model="group[0]['group']['ratio']">
                      <div :class="['chart-cover']" slot="left">
                        <oBaseChart
                          :config="group[0]"
                          :localData="localData"
                          identification="grid"
                          :title="funName + '_0'"
                        ></oBaseChart>
                      </div>
                      <div :class="['chart-cover']" slot="right">
                        <oBaseChart
                          :config="group[1]"
                          :localData="localData"
                          identification="grid"
                          :title="funName + '_1'"
                        ></oBaseChart>
                      </div>
                    </Split>
                  </template>
                </div>
              </template>
            </div>
            <!-- toolbar -->
            <template v-slot:toolbar_buttons>
              <o-toolbar
                v-if="toolbar !== null"
                :config="toolbar"
                :option="{ panel: isBasePanel }"
                :graph="graphGroup"
                :searchIsSwitch="searchCanSwitch"
                :searchMode="isLexicon"
                @commit-event="commitEvent"
                @globalSearch="globalSearch"
                @globalSeachValChange="globalSeachValChange"
                @switchSearchMode="switchSearchMode"
                ref="toolbar"
                :filterToolbarStatus="filterToolbarStatus"
              >
              </o-toolbar>
            </template>
          </vxe-grid>
        </div>
      </Split>
    </div>
    <!-- 这里应该写成oModal动态加载 -->
    <o-modal
      v-model="isOpenPrint"
      :title="$srv.getI18nByPath('vxe.print.selPrintTemp')"
      :size="[300, 400]"
      :mask="true"
      :tap-close="true"
      @on-ok="doPrint"
    >
      <o-print-panel
        slot="content"
        :funID="funID"
        @on-change="val => (selectedPrintTemp = val)"
      ></o-print-panel>
    </o-modal>
    <!-- 高级检索 -->
    <o-modal
      v-model="isOpenSearch"
      :title="$srv.getI18nByPath('vxe.search.advSearchCheck')"
      :size="[400, 300]"
      :mask="false"
      :tap-close="true"
      :keep-alive="true"
      @on-ok="doSearch"
      :ok="$srv.getI18nByPath('vxe.search.searchCheckConfirm')"
    >
      <div class="search-box" slot="content">
        <o-base-form ref="searchForm" :mode="2"></o-base-form>
      </div>
      <Button class="search-footer" @click="resetSearchForm" slot="footer">
        {{ $srv.getI18nByPath('vxe.menu.reset') }}
      </Button>
    </o-modal>
    <!-- <filterModal
      v-model="filterModalShow"
      @status="filterStatusChange"
      :columns="tableColumns"
      :loadfilter="loadFilterList"
    ></filterModal> -->

    <!-- 双击编辑窗 -->
    <rowEditModal
      v-model="columnEditModal.isShow"
      @statusChangeCopy="
        e => {
          columnEditModal.isShow = e;
        }
      "
      @on-change="rowEditChange"
      @on-field-event="onFieldEvent"
      :tableEditor="GT_editor"
      :tableColumns="tableColumns"
      :currentRowData="currentRowData"
      :config="columnEditModal.config"
      :rowStatus="columnEditModal.editStatus"
      :permission="columnEditModal.permission"
    ></rowEditModal>
  </div>
</template>
<script lang="ts">
import { N_grid, N_oSetupPanel } from '@/types';
import { RowInfo } from 'vxe-table';
import {
  Clipboard,
  filterModal,
  Grid,
  gridFlowchart,
  I_editor,
  I_storeData,
  I_tableBehavior,
  ifs,
  MenuFirstOption,
  N_oBaseGrid,
  oModal,
  oToolbar,
  rowEditModal,
  Sortable,
  T_conf,
  T_editor,
  T_srv,
  ts,
  Tsrv,
  vue,
  vxeConfig
} from './config';

@T_srv.comp({
  components: {
    oToolbar,
    oModal,
    filterModal,
    gridFlowchart,
    rowEditModal
  }
})
export default class oBaseGrid extends vue {
  [x: string]: any;

  filterModalShow: number = -1;

  $refs!: {
    xGrid: Grid;
  };

  @T_srv.prop({
    type: Object,
    default: () => {}
  })
  config!: any;

  @T_srv.prop({ default: '', required: false }) readonly parentName!: string;

  @T_srv.prop({ default: 0, required: false }) readonly parentID!: number;

  @T_srv.prop({ default: 0, required: false }) readonly mode!: number;

  // 编辑锁 默认开启
  @T_srv.prop({ default: true, required: false, type: Boolean })
  isUseEditLock: boolean;

  // 每行是否要多选框
  @T_srv.prop({ default: true, required: false })
  readonly multipleSelection!: boolean;

  // 是否要组件协调
  @T_srv.prop({ default: true, required: false })
  readonly isCoordination!: boolean;

  // 更换总线事件名
  // 1.0通过内部默认事件在组件间通讯
  // 当标准baseGrid为定制程序里的组件时会存在相互干扰
  @T_srv.prop({
    required: false,
    type: Array,
    default: () => []
  })
  regCustEventName: Array<N_oBaseGrid.I_regCustEventName>;

  // 当此组件是由oMagicBox容器建立时,执行okMagicBox()出发o-magicBox提交数据
  @T_srv.inject({ default: () => {} }) okMagicBox;

  @T_srv.inject({ default: () => {} }) addTabFunc;

  /* 父组件compBoxInfo */
  @T_srv.prop({
    required: false,
    type: Object,
    default: null
  })
  compBoxInfo: ifs.I_compBoxInfo;

  /* 组件类型（basegrid、baseview-视图、refbasegrid-引用实表） */
  @T_srv.prop({
    required: false,
    default: 'basegrid'
  })
  tableType: string;

  private name: string = 'oBaseGrid';

  /* 组件名 */
  private G_compName: string = this.name;

  /* 组件箱信息对象 */
  private GT_compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱对象 */
  private GT_compBox: ifs.I_compBox;

  /* 组件箱识别ID */
  private G_compID: string;

  private gridID: string = '';

  public filterToolbarStatus = false;

  // 列拖动插件实例（销毁组件时会用到）
  public sortable2: any;

  // 表格实例
  private chartRef!: HTMLElement;

  private isEmpty = Tsrv.utils.isEmpty;

  /**
   * 固定配置和变量
   */
  // 输入设置
  private importConfig: any = T_conf.importConfig();

  // 输出设置
  private exportConfig: any = T_conf.exportConfig(this.exportMethod);

  // 排序设置
  private sortConfig: any = T_conf.sortConfig();

  // 过滤设置
  private filterConfig: any = T_conf.filterConfig();

  // 自带tool，全屏和显示
  private defaultToolbar: any = T_conf.defaultToolbar();

  // 默认编辑配置
  private defaultEditConfig: any = T_conf.defaultEditConfig(
    // this.editActiveMethod 弃用
    this.beforeEditMethod
  );

  // 默认style设置
  private defaultTableStyle = T_conf.defaultTableStyle();

  // 默认page配置
  private tablePage = T_conf.tablePage();

  private customConfig = T_conf.customConfig(
    this.customCheckMethod,
    this.updateStore,
    this.restoreStore,
    this.customVisibleMethod
  );

  public moduleName: string = 'basegrid';

  // seq 开启时起始值
  private seqStartIndex: number = 0;

  // 是否在加载
  private loading: boolean = false;

  // 是否自治
  private isIndependent: boolean = true;

  private isBasePanel: boolean = false;

  // 是否开启回撤等热键
  private isHotKeyActive: boolean = false;

  private isOpenPrint: boolean = false;

  private isOpenSearch: boolean = false;

  private selectedPrintTemp: object = {};

  // 监听类型
  private listenType: string = 'default';

  // 是否可编辑
  private isEditable: boolean = false;

  // 是否显示footer
  private isShowFooter: boolean = false;

  // 是否使用服务器footer数据
  private isFooterRemote: boolean = true;

  private dataSource: string = '';

  // 数据源/ table/advq
  private advqParams: any = null;

  private isCtrl: boolean = false;

  private isShift: boolean = false;

  private isAlt: boolean = false;

  // private cancelAxios: any = null;

  private needSave: boolean = false;

  private userSelect: string = 'text';

  private gridHeight: number = 0;

  public graphGroup = null;

  /**
   * 属性变量
   */
  private cellStyleCfg: any = [];

  private columnStyleCfg: any = [];

  private rowStyleCfg: any = [];

  private rowEditCfg: any = [];

  private cellEditCfg: any = [];

  private columnEditCfg: any = [];

  private columnVisibleCfg: any = [];

  // private actionsCfg: any = {};

  private headerGroup: any = [];

  private searchColumns: any = [];

  private charts = {};

  private editConfig: any = this.defaultEditConfig;

  private pagerConfig: any = null;

  // 右键菜单
  private contextMenu: any = false;

  // table的字段
  private tableColumns: any = null;

  private storedColumns: any = null;

  // table的验证
  private validRules: any = null;

  // table的toolbar
  private toolbar: any = null;

  // table的互动
  private messageConfig: any = null;

  // table样式
  private tableStyle: any = null;

  private tableDataSetting: any = null;

  // table的数据设置
  // 当本表对应本表时的主要字段
  public keyField: string = '';

  public reportPlanID: number = 0;

  // private editModalShow = false;

  private rowEditModalShow = false;

  private columnEditModal: any = {
    isShow: this.config?.triggerEvent?.rowDbClick ?? false,
    config: this.config?.triggerEvent ?? null,
    permission: this.config?.permission,
    editStatus: 'none'
  };

  private currentRowData: any = {};

  /**
   * 功能变量
   */
  // 此值由GT_edit维护
  private tableName: string = '';

  // 功能名 //此值由GT_edit维护
  public funName: string = '';

  // 主功能名
  public mainFunName: string = '';

  // 当前选中的单元格
  private current: any = T_conf.current();

  // 数据存储
  private cloudData = [];

  private localData = [];

  private storedSelection = []; // 多选信息存储

  // QBE
  private rule: any = T_conf.rule();

  // 存储所有m2o的配置，所有m2o字段对应的默认值
  private m2oSetting: { [key: string]: any } = {};

  private slcSetting: { [key: string]: any } = {};

  private pidSetting: { [key: string]: any } = {}; // pid

  private pendingFilter = [];

  // // 更新范围
  // private scope = T_conf.scope();

  private subQueryArr: string[] = [];

  private footerData: { [key: string]: string } = {};

  private layoutMode = 0;

  private linkParent: any = T_conf.linkParent();

  // // 编辑状态
  private editStatus: boolean = false;

  private copyColunm: { [key: string]: string } = T_conf.copyColunm();

  public GT_editor: I_editor = undefined;

  public funID: string = '';

  public grid: any = null;

  private defListenersEventNames: Array<string> = [];

  // 已调入编辑锁资料
  private isLoadEditLock: boolean = false;

  private currDefaultBusEventName: string = '';

  private qbeQuery: boolean = false;

  private gridHead: any = {
    qbeSearch: false,
    bancodeScan: false
  };

  private isMask: boolean = false;

  private customPermission: any = null;

  private _config: any;

  private searchControl = {
    split: 0,
    modeStyle: 'vertical',
    formPosition: 'top',
    gridPosition: 'bottom'
  };

  // 分割面板样式
  private collapseStyle: any = { '--splitTrigger': 'none' };

  // 表格元素
  private gridEl: HTMLElement | null = null;

  //
  private customBtnStatus: Array<object> = [];

  private nonePermission: boolean = false;

  // 用户行为数据
  private customStoreData: I_tableBehavior;

  // 固定列，显隐，排序，宽度
  private storeData: I_storeData;

  // 是否显示表格 还是画布
  private displayModel: boolean = true;

  // 右键菜单实例
  private contextMenuEl: HTMLElement | null = null;

  // 表格操作列的配置
  private operateColumnConfig: N_oBaseGrid.I_operateColumnConfig = T_conf.operateColunmCfg();

  // 国际化翻译字段
  private funI18nFields: Array<any> = [];

  // 是否 分词搜索
  private isLexicon: boolean = false;

  private searchCanSwitch: boolean = false;

  // watch
  @T_srv.watch('$i18n.locale')
  watchI18nData(val) {
    // i18n右键功能
    this.updateContextMenu();
  }

  @T_srv.watch('config')
  onConfigChange(config: any) {
    this.init(config);
  }

  @T_srv.watch('editStatus')
  watchEditStatus(newV: any) {
    if (this.listenType === 'default') {
      this.sendBusEvent(
        'bus',
        'bus_basegrid_editStatus',
        newV,
        this.mainFunName
      );
    } else if (this.listenType === 'magicbox') {
      this.sendBusEvent('bus', 'bus_magicbox_editStatus', newV);
    }
    this.GT_editor.setCustBtnStatusByEditStatus(newV);
  }

  created() {
    this._config = Tsrv.utils.clone(this.config, true);
    this.GT_compBoxInfo = Tsrv.getCompInfo(this.compBoxInfo);
    this.G_compID = this.GT_compBoxInfo.compID;
    this.GT_compBox = this.GT_compBoxInfo.TcompBox;
    this.GT_editor = new T_editor(this, this.GT_compBoxInfo);
    this.GT_compBox.addCompMergeName(
      this.G_compID,
      'oBaseGridEditor',
      this.GT_command
    );
    // 本地主编辑类
    this.init(this._config);

    // gridID vxe-table 在保存默认配置到本地时的会引用gridID
    this.gridID = `${this.mainFunName}-${this.GT_editor.getFunName()}`;
    this.GT_editor.setGridID(this.gridID);
    // 如果有父组件，则表名从父组件获得
    if (this.parentName !== '') {
      this.isIndependent = false;
      this.GT_editor.setFunName(this.parentName).setTableName(this.parentName);
      this.isBasePanel = true;
      if (
        this._config.originComp === 'custom' &&
        this._config.originName !== ''
      ) {
        this.GT_editor.setTableName(this._config.originName);
      }
    }
    if (this.mode === 0) {
      // 单档
      if (this.funName === this.mainFunName) {
        this.funID = Tsrv.getMinFunID(this.funName);
      } else {
        this.funID = Tsrv.getDeputyFunID(this.mainFunName, this.funName);
      }
      if (Tsrv.utils.noValue(this.funID)) {
        console.error('funID is null');
      }
      this.GT_editor.setFunID(this.funID);
    }
    // 初始排序——_sort_默认排序
    this.GT_editor.addSort('_sort_', 'asc');
  }

  async mounted() {
    this.GT_compBox.addCompMergeName(this.G_compID, this.G_compName, this);
    this.$emit('compBoxInfo', this.GT_compBoxInfo);
    /* 最终应用组件向外抛出引用实例,以供应用间调用 */
    Tsrv.compBox.addCompMergeName(
      Tsrv.compBox.getDefGUID(), // 全局compBox
      this.funName,
      this
    );
    this.grid = this.$refs.xGrid;
    this.gridEl = (this.grid as Vue).$el as HTMLElement;
    this.GT_editor.setGrid(this.$refs.xGrid);
    this.GT_editor.setLang(this.$i18n.locale || 'en-US');
    this.GT_editor.setToolbar(this.$refs['toolbar']);
    // 启动轮询事件
    this.GT_editor.startPollingEvent();

    // 配置autoload
    // 加载数据，如果自动加载关闭，或者为单功能显示，则autoload关闭
    if (this._config) {
      if (this.GT_editor.getActionCfg()?.openFun) {
        await this.handleActions(
          this.GT_editor.getActionCfg().openFun,
          'openFun'
        );
      }
      if (this.isIndependent) {
        if (this._config['isAutoload'] !== undefined) {
          if (this._config['isAutoload'] === true) {
            this.$nextTick(() => {
              this.GT_editor.loadTableData();
            });
          }
        } else {
          if (this.tableDataSetting.autoload !== false) {
            // this.GT_editor.searchFilterChange();
            this.$nextTick(() => {
              this.GT_editor.loadTableData();
            });
          }
        }
      }
      // 配置监听listentype
      this.listenType = this._config['listenType'] || 'default';
      this.$nextTick(() => {
        this.$emit('mounted', this);
      });
    }
    // 如果没有父组件，则监听自身
    if (this.isIndependent) {
      // const eventName: string = this.GT_editor.getFunName();
      this.getDefListener();

      this.defListenersEventNames.forEach(eN => {
        const newEventName: string = this.GT_editor.getRegEventName(
          'receive',
          eN
        );
        // eN 如果没有custDefListener,eN默认为功能名
        this.currDefaultBusEventName = newEventName ?? eN;
        if (this.listenType === 'default') {
          this.$bus.$on(newEventName ?? eN, (msg: any) => {
            if (
              msg.listenType === this.listenType ||
              msg.type === 'coordination'
            )
              this.handleListener(msg);
          });
        } else {
          this.$mbus.$on(newEventName ?? eN, (msg: any) => {
            if (msg.listenType === this.listenType) this.handleListener(msg);
          });
        }
      });
    }

    // 初始化列拖动
    this.initSortTable();

    // 表格（自适应--注册）元素获取
    setTimeout(() => {
      const erd = this.$elementDetecter();
      this.reframe(this.gridEl);
      erd.listenTo(this.gridEl, (el: any) => {
        this.reframe(el);
      });
      this.listenGridBody();
    }, 0);

    this.reFiexedandDraggable();
  }

  beforeDestroy() {
    if (this.GT_editor.getActionCfg()?.closeFun) {
      this.handleActions(this.GT_editor.getActionCfg().closeFun, 'closeFun');
    }
    // 销毁列拖动实例
    if (this.sortable2) {
      this.sortable2.destroy();
    }
    this.$bus.$off(
      this.GT_editor.getRegEventName('receive', 'selBillMagicBox') ??
        'selBillMagicBox'
    );
    if (this.listenType === 'default') {
      this.defListenersEventNames.forEach(eN => {
        this.$bus.$off(
          this.GT_editor.getRegEventName('receive', 'selBillMagicBox') ?? eN
        );
      });
    } else {
      this.defListenersEventNames.forEach(eN => {
        this.$mbus.$off(
          this.GT_editor.getRegEventName('receive', 'selBillMagicBox') ?? eN
        );
      });
    }
    this.recordbBehaviorBeforeDesrory();

    // 删除GridBody右键监听事件
    const gridBodyEl = document.querySelector('.vxe-table--body-wrapper');
    if (!Tsrv.noValue(gridBodyEl)) {
      gridBodyEl.removeEventListener('contextmenu', this.listenContextMenu);
    }
  }

  destroyed() {
    /* 注册组件销毁 */
    this.GT_compBox.removeCompMergeName(this.G_compID, this.G_compName);
    /* 最终应用组件销毁 */
    Tsrv.compBox.removeCompMergeName(Tsrv.compBox.getDefGUID(), this.funName);
    // 关闭轮询事件
    this.GT_editor.stopPollingEvent();

    /* 如果父组件传入的compBoxInfo则删除本文件产生的引用,反之是本组件产生的ID统一删除 */
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        `'${this.G_compName}'`
      ]);
    }
  }

  private getDefListener() {
    const custDefListener = this._config?.messageConfig?.custDefListener;
    if (!Tsrv.utils.noValue(custDefListener)) {
      let isNull = true;
      Object.keys(custDefListener).forEach(key => {
        if (!Tsrv.utils.noValue(custDefListener[key])) {
          isNull = false;
          if (Array.isArray(custDefListener[key])) {
            this.defListenersEventNames.push(...custDefListener[key]);
          } else if (typeof custDefListener[key] === 'string') {
            this.defListenersEventNames.push(custDefListener[key]);
          } else {
            throw new Error(`无法识别的事件监听[${custDefListener[key]}]`);
          }
        }
      });
      if (isNull) {
        this.defListenersEventNames.push(this.GT_editor.getFunName());
      }
    } else {
      this.defListenersEventNames.push(this.GT_editor.getFunName());
    }
  }

  filterStatusChange(e: any) {
    this.filterModalShow = e.v;
    if (e.fts) {
      for (let i = 0; i < e.filters.length; i++) {
        if (
          e.filters[i].field &&
          e.filters[i].val &&
          e.filters[i].val.length > 0
        ) {
          this.GT_editor.clearFilter();
          this.filterToolbarStatus = e.fts;
          break;
        }
      }
      let L_tp = null;
      for (let i = 0; i < e.filters.length; i++) {
        if (
          e.filters[i].field &&
          e.filters[i].val &&
          e.filters[i].val.length > 0
        ) {
          L_tp =
            typeof e.filters[i].val === 'string'
              ? e.filters[i].val
              : e.filters[i].val
                  .map(el => {
                    return this.replaceSensitive(el);
                  })
                  .join('|');
          L_tp = Tsrv.utils.valueToFilter('string', 'custom', L_tp).value;
          this.GT_editor.addFilter(
            this.tableColumns[e.filters[i].field].field,
            L_tp,
            false
          );
        }
      }

      L_tp && this.GT_editor.loadTableData();
    }
  }

  public getScope() {
    return this.GT_editor.getScope();
  }

  // 初始化列拖动
  private initSortTable() {
    this.$nextTick(() => {
      const $table = this.$refs.xGrid;
      // 创建拖动元素实例
      this.sortable2 = new Sortable(
        $table.$el.querySelector(
          '.body--wrapper>.vxe-table--header .vxe-header--row'
        ),
        {
          handle: '.vxe-header--column',
          onEnd: ({ item, newIndex, oldIndex }) => {
            // 拖动结束触发的回调函数
            const { fullColumn, tableColumn }: any = $table.getTableColumn();
            // 通过下表获取拖动前后被改动的两列
            const L_oldCol = tableColumn[oldIndex];
            const L_newCol = tableColumn[newIndex];
            const targetThElem = item;
            const wrapperElem = targetThElem.parentNode;
            if (
              L_oldCol.title === 'ID' ||
              L_oldCol.title === '#' ||
              L_oldCol.type === 'checkbox' ||
              // L_oldCol.params.source.noDragging === true ||
              !Tsrv.noValue(L_oldCol.fixed) ||
              L_newCol.title === 'ID' ||
              L_newCol.title === '#' ||
              L_newCol.type === 'checkbox' ||
              // L_newCol.params.source.noDragging === true
              !Tsrv.noValue(L_newCol.fixed)
            ) {
              // 排除固定列不允许拖动，并还原已拖动元素
              const oldThElem = wrapperElem.children[oldIndex];
              if (newIndex > oldIndex) {
                wrapperElem.insertBefore(targetThElem, oldThElem);
              } else {
                wrapperElem.insertBefore(
                  targetThElem,
                  oldThElem ? oldThElem.nextElementSibling : oldThElem
                );
              }
              // this.$msg(Tsrv.getI18nByPath('oBaseGrid.noDrag'));
              this.$Message.warning(Tsrv.getI18nByPath('oBaseGrid.noDrag'));
              return;
            }
            // 获取列在总的列配置的列表中的实际下标（参考getTableColumn函数的解释）
            // 注意：vxetable未显示的列在实际dom元素中也是不存在的（不是通过样式隐藏，而是直接不渲染的），
            // 但是在总的列配置的列表中是存在的，
            // 所以此处回调函数的参数的两个下标并不代表被拖动的列在总的列配置的列表中的实际下标，代表的只是已显示的列的列表中的下标，
            // 也就是实际渲染出来的dom元素在父元素的子元素列表中的下标，因此需要将dom元素下标转换成总的列配置的列表中的下标。
            // 做法：通过tableColumn和回调函数的参数下标获取到列，再通过getColumnIndex获取到列实际的下标，
            // 然后将总的列配置的列表中的列，按照拖动的结果重新排列(调换位置)
            // 最后在通过loadColumn重新读取列配置。
            const oldColumnIndex = $table.getColumnIndex(L_oldCol);
            const newColumnIndex = $table.getColumnIndex(L_newCol);

            const currCol = fullColumn.splice(oldColumnIndex, 1)[0];
            fullColumn.splice(newColumnIndex, 0, currCol);
            $table.loadColumn(fullColumn);
            const StoreData = $table.getCustomStoreData();
            this.updateStore({
              id: this.gridID,
              type: 'drag',
              storeData: StoreData
            });
          }
        }
      );
    });
  }

  private customCheckMethod({ column }) {
    if (column.property && this._config) {
      const field: string =
        column.editRender.name === 'oM2oSelector'
          ? column.property.split('|')[1]
          : column.property;
      // const find = Tsrv.utils.find(
      //   this._config.tableColumns,
      //   el => el.field === field
      // );
      // // if (find && find.isShow !== true) {
      // //   return false;
      // // }
      const usable = this.operateColumnConfig.usable;
      return usable.has(field);
    }
    return true;
  }

  private customVisibleMethod({ column }) {
    if (column.property && this._config) {
      const field: string =
        column.editRender.name === 'oM2oSelector'
          ? column.property.split('|')[1]
          : column.property;
      // const find = Tsrv.utils.find(
      //   this._config.tableColumns,
      //   el => el.field === field
      // );
      // // if (find && find.isShow !== true) {
      // //   return false;
      // // }
      const display = this.operateColumnConfig.display;
      return display.has(field);
    }
    return true;
  }

  // 重写默认的列配置，用于用户行为，（重写显示列，列宽度）
  private restoreStore(params: { id; type; storeData }): Promise<any> {
    return new Promise((resolve, reject) => {
      this.storeData = Tsrv.TPP.getFunBehaviorByFunName(params.id).storeData;
      this.storeData ? resolve(this.storeData) : resolve(params.storeData);
    });
  }

  // mounted中重写固定列，列顺序
  private reFiexedandDraggable() {
    let { fullColumn } = this.grid.getTableColumn();
    // 用户行为：固定列
    if (!Tsrv.noValue(this.storeData?.fixedData)) {
      for (const key in this.storeData.fixedData) {
        for (const iterator of fullColumn) {
          if (iterator.field === key && !Tsrv.noValue(iterator.fixed)) {
            // 如果配置中存在固定列，依配置为主
            iterator.fixed = this.storeData.fixedData[key];
            break;
          }
        }
      }
    }
    // 用户行为：列顺序
    if (!Tsrv.noValue(this.storeData?.sortData)) {
      // 如果存在用户配置新增字段，则不使用偏好配置
      let isInsert = false;
      const data = fullColumn.map(item => item.field).splice(3);
      data.forEach(item => {
        if (!this.storeData.sortData[item]) {
          isInsert = true;
        }
      });
      if (isInsert) {
        // 更新用户行为数据
        const StoreData = this.grid.getCustomStoreData();

        this.updateStore({
          id: this.gridID,
          type: 'sort',
          storeData: StoreData
        });
        this.recordbBehaviorBeforeDesrory();
        Tsrv.TPP.saveBehaviorData();
        return;
      }

      const columns = [];
      // 前两个字段分别为checkBox，seq，不做排序处理
      for (let i = 0; i <= 2; i++) {
        columns.push(fullColumn[i]);
      }
      // 后续字段根据用户行为配置
      for (const key in this.storeData.sortData) {
        for (let i = 3; i < fullColumn.length; i++) {
          if (fullColumn[i].field === key) {
            columns[this.storeData.sortData[key] - 1] = fullColumn[i];
            break;
          }
        }
      }

      if (columns.length === fullColumn.length) {
        fullColumn = columns;
        this.grid.loadColumn(fullColumn);
      }
    }
  }

  private findEmptyIndex(arr: any[]) {
    for (let i = 0; i < arr.length; i++) {
      if (!(i in arr)) {
        return i; // 返回第一个空位的索引
      }
    }
    return -1; // 无空位
  }

  // 用户触发行为，用于记录
  private updateStore(params: { id; type; storeData }): Promise<any> {
    return new Promise((resolve, reject) => {
      this.customStoreData = Tsrv.utils.clone(params, true);
      this.customStoreData.type = 'restore';
      resolve(params.storeData);
    });
  }

  // 关闭前记录用户行为
  private recordbBehaviorBeforeDesrory() {
    // 如果用户没有行为数据，则不记录
    if (Tsrv.noValue(this.customStoreData)) {
      return;
    }
    const storeData = {
      key: this.funName,
      value: this.customStoreData
    };
    Tsrv.TPP.recordBehaviorData(this.mainFunName, storeData);
  }

  /**
   * editActiveMethod 当前编辑激活方法
   */
  private beforeEditMethod({ row, rowIndex, column, columnIndex }) {
    let result = true;
    // 非新建行
    // if (row.id) {

    if (this.GT_editor.editorStatus !== 'new') {
      // 非新建行，非修改状态不允许编辑
      if (!this.isEditable) {
        result = false;
      } else {
        if (this.isUseEditLock) {
          if (!this.isLoadEditLock) {
            return false;
          }
          if (this.GT_editor.editLocked.has(row.id)) {
            return false;
          }
        }
      }
    }

    if (column.property === 'id') {
      result = false;
    }

    if (column.params && column.params.disabled === true) {
      result = false;
    }

    // 子查询字段不允许编辑
    if (this.subQueryArr.indexOf(column.title) > -1) {
      result = false;
    }

    // 已审核字段不允许编辑??
    // if (row['FStatus'] !== undefined) {
    //   if (row['FStatus'] === 1) {
    if (row['_audited_'] !== undefined) {
      if (row['_audited_'] === 1) {
        result = false;
      }
    }

    // 功能配置不允许编辑的不允许编辑
    if (column.editRender) {
      if (column.editRender.props) {
        if (column.editRender.disabled === true) {
          result = false;
        }
      }
    }

    if (!Tsrv.utils.isEmpty(this.columnEditCfg)) {
      for (let i = 0; i < this.columnEditCfg.length; i++) {
        if (this.columnEditCfg[i].field === column.property) {
          if (
            vxeConfig.grid.verifyRules(row, this.columnEditCfg[i].conditions)
          ) {
            result = this.columnEditCfg[i].editable;
            break;
          }
        }
      }
    }

    if (!Tsrv.utils.isEmpty(this.rowEditCfg)) {
      for (let i = 0; i < this.rowEditCfg.length; i++) {
        if (vxeConfig.grid.verifyRules(row, this.rowEditCfg[i].conditions)) {
          result = this.rowEditCfg[i].editable;
          break;
        }
      }
    }

    if (!Tsrv.utils.isEmpty(this.cellEditCfg) && column.property) {
      for (let i = 0; i < this.cellEditCfg.length; i++) {
        const columnName =
          column.property.indexOf('|') > -1
            ? column.property.split('|')[1]
            : column.property;
        if (this.cellEditCfg[i].field === columnName) {
          if (vxeConfig.grid.verifyRules(row, this.cellEditCfg[i].conditions)) {
            result = this.cellEditCfg[i].editable;
            break;
          }
        }
      }
    }
    return result;
  }

  /**
   * init 初始化
   * mode = 0: 从完全config中初始化
   */
  public init(config: any) {
    this.GT_editor.setDbType(config?.dbType || 'mysql');
    this.setFunI18nFields(config?.funI18nFields);
    if (config?.funLexicon) {
      this.searchCanSwitch = true;
      this.isLexicon = true;
    }
    if (this.mode === 0) {
      if (config.originComp === 'custom' && config.originName !== '') {
        this.GT_editor.setFunName(config.name).setTableName(config.originName);
      } else {
        this.GT_editor.setFunName(config.name).setTableName(config.name);
      }
      // 配置style
      this.tableStyle = config.tableStyle || this.defaultTableStyle;
      // 配置pager
      this.pagerConfig = this.tableStyle.showPager ? this.tablePage : false;
      this.mainFunName = this._config?.mainFun || '';
      this.GT_editor.setMainFunName(this.mainFunName);
      const cols = config.tableColumns || config.formColumns;

      const columns = cols.filter(el => !!el?.nodeData === false);

      this.GT_editor.newTcompCoordination(this._config);
      this.initToolbarPms();
      this.initColumnsPms(columns);
      this.updateContextMenu();
      this.initQBE();
      this.initExtraPart();

      // 配置datasetting
      this.tableDataSetting = config.tableDataSetting || {
        footerMethod: () => {},
        autoload: true
      };

      // 配置验证规则
      this.validRules = vxeConfig.grid.getValidRules(columns);

      this.setHeaderGroup(config.headerGroup);

      this.setCharts(config.charts);
      // if (!Tsrv.utils.isEmpty(this.charts)) {
      //   setTimeout(() => {
      //     const erd = this.$elementDetecter();
      //     this.chartRef = this.$refs['chart'] as HTMLElement;
      //     erd.listenTo(this.chartRef, (el: any) => {
      //       // this.sendBusEvent('bus',newEventName ?? 'chartResize', '');
      //     });
      //   }, 0);
      // }

      // 配置字段
      this.tableColumns = this.transformColumns(columns);

      this.dataSource = 'table';

      // 页脚规则 （现 config的tableDataSetting中没有isFooterRemote属性配置，且getpartdata中暂没发现有footer属性，故无法使用服务器footer数据）-- 改默认为：false
      this.isFooterRemote =
        this.tableDataSetting.isFooterRemote === undefined
          ? false
          : this.tableDataSetting.isFooterRemote;

      // 配置行列单元格规则
      this.setRules(config.rules);
      this.GT_editor.setActionCfg(config.action);

      // 配置信息传递
      this.messageConfig = config.messageConfig || null;

      // 功能“浏览”权限
      const defaultPermission = Tsrv.utils.find(
        this._config.permission,
        item => item.area === 'default'
      );
      this.nonePermission = !defaultPermission?.data?.browse;
    } else if (this.mode === 1) {
      this.isIndependent = false;
      this.isFooterRemote = false;
      this.pagerConfig = this.tablePage;
      this.tableStyle = this.defaultTableStyle;
      this.tableDataSetting = {
        footerMethod: () => {},
        autoload: true
      };
      this.validRules = {};
      this.messageConfig = null;
    }
  }

  public initQBE() {
    this.rule.QBE.funName = this._config.QBE?.funName || '';
    this.rule.QBE.fieldName = this._config.QBE?.fieldName || '';
  }

  public initToolbarPms() {
    this.toolbar = vxeConfig.getToolbarConfig(
      this._config.toolbar || {},
      // 'basegrid'
      this.tableType
    );

    if (this._config.queryLink && this._config.queryLink.length > 0)
      this.toolbar['queryLink'] = this._config.queryLink;
    if (this._config.selbill && this._config.selbill.length > 0)
      this.toolbar['selbill'] = this._config.selbill;
    // this.defaultToolbar = this.tableStyle.showToolbar
    //   ? this.toolbar.default.isShow
    //     ? this.defaultToolbar
    //     : {}
    //   : false;
    if (!this.tableStyle.showToolbar) {
      this.defaultToolbar['enabled'] = false;
    }

    const toolbarPermission = Tsrv.utils.find(
      this._config.permission,
      el =>
        el.area === 'toolbar' && (el.type === 'button' || el.type === 'NULL')
      // && el.data.insert !== undefined
    );
    if (toolbarPermission) {
      const data = toolbarPermission.data;
      for (const key in this.toolbar) {
        if (data[key]) {
          this.toolbar[key].auth = !!data[key];
        }
      }
    }

    if (this._config.tableDataSetting?.editable === false) {
      this.toolbar.edit && (this.toolbar.edit.auth = false);
      this.toolbar.insert && (this.toolbar.insert.auth = false);
      this.toolbar.delete && (this.toolbar.delete.auth = false);
      this.toolbar.save && (this.toolbar.save.auth = false);
      this.toolbar.import.auth = false;
    }

    this.toolbar.insert && (this.toolbar.insert.isDisable = false);
    // this.toolbar.audit.isDisable = true;
    this.GT_editor.requestAuditBtnStatus('isDisable', true);
    this.toolbar.save && (this.toolbar.save.isDisable = false);
    this.toolbar.edit && (this.toolbar.edit.value = false);
    // this.toolbar.delete.isDisable = true;
    // this.toolbar.save.isDisable = true;
    // this.toolbar.edit.value = false;

    this.customPermission = Tsrv.utils.find(
      this._config.permission,
      el => el.area === 'toolbar' && el.type === 'customButton'
    );

    if (
      this.customPermission &&
      this.toolbar['addon'] &&
      this.toolbar['addon'].length > 0
    ) {
      const data = this.customPermission.data;
      this.toolbar['addon'].forEach(el => {
        !Object.prototype.hasOwnProperty.call(el, 'isShow') &&
          (el['isShow'] = true);
        el.auth = !!data[el.title];
        if (el?.initDisabled === true) {
          el.auth = false;
        }
        if (el?.initNotshow === true) {
          el['isShow'] = false;
        }
        if (el.children.length > 0) {
          el.children.forEach(child => {
            child.auth = !!data[child.title];
          });
        }
      });
      // 获取永久储存自定义按钮状态的按钮————并初始化更新状态  （功能打开时、刷新时、）
      this.GT_editor.getCustBtnStatus();
    }
    const selbillPermission = Tsrv.utils.find(
      this._config.permission,
      el => el.area === 'toolbar' && el.type === 'selbill'
    );
    if (
      selbillPermission &&
      this.toolbar['selbill'] &&
      this.toolbar['selbill'].length > 0
    ) {
      const data = selbillPermission.data;
      this.toolbar['selbill'].forEach(el => {
        el.auth = !!data[el.id];
      });
    }
    this.toolbar.qbeSearch = {
      auth: true,
      isDisable: false,
      isShow:
        this._config.status === 'main' &&
        Tsrv.getx(this._config, 'qbeSearch.enable', false),
      value: null
    };
    this.toolbar.bancodeScan = {
      auth: true,
      isDisable: false,
      isShow: Tsrv.getx(this._config, 'bancodeScan.enable', false),
      value: null
    };
    // 当设置为 双击行编辑时 需要隐藏 “删除”、“保存”、“编辑”按钮
    if (Tsrv.getx(this._config, 'triggerEvent.rowDbClick', false)) {
      this.toolbar.save && (this.toolbar.save.isShow = false);
      this.toolbar.edit && (this.toolbar.edit.isShow = false);
    }
  }

  public initColumnsPms(columns: any) {
    const tablePermission = Tsrv.utils.find(
      this._config.permission,
      el => el.area === 'table'
    );
    if (tablePermission) {
      const data = tablePermission.data;

      for (const item in data) {
        const key = Tsrv.utils.find(columns, el => el.field === item);
        if (key && !!data[item] === false) {
          key.isShow = false;
        }
      }
    }
  }

  private setCharts(config: any, update: boolean = false) {
    return new Promise(resolve => {
      if (config) {
        const groups = Tsrv.utils.groupBy(config, 'groupName');

        for (const key in groups) {
          groups[key].forEach(item => {
            if (this.graphGroup) {
              const find = Tsrv.utils.find(
                this.graphGroup,
                el => el.name === key
              );
              item.isShow = find ? find.value : false;
            }
            if (item.group.ratio === '') item.group.ratio = 100;
            item.group.ratio =
              typeof item.group.ratio === 'number'
                ? item.group.ratio
                : Tsrv.utils.toNumber(item.group.ratio) / 100;
          });
        }
        this.charts = groups;
        setTimeout(() => {
          let chartFlag = false;
          for (const key in this.charts) {
            if (this.charts[key][0].isShow) {
              chartFlag = true;
            }
          }
          this.gridHeight = Object.keys(this.charts).length * 300;
          if (!this.graphGroup) {
            this.graphGroup = Object.keys(this.charts).map(el => {
              return {
                name: el,
                label: el,
                // name: 'chart',
                // label: 'oBaseGrid.chart',
                value: this.charts[el][0].isShow
              };
            });
            this.graphGroup.push({
              name: 'table',
              // label: "表格",
              label: 'oBaseGrid.table',
              value: true
            });
          }
          if (chartFlag) {
            if (this.graphGroup) {
              const find = Tsrv.utils.find(
                this.graphGroup,
                el => el.name === 'table'
              );
              this.layoutMode = find
                ? find.value
                  ? 1
                  : this.toolbar
                  ? 2
                  : 3
                : 1;
            } else {
              this.layoutMode = 0;
            }
          } else {
            this.layoutMode = 0;
          }
          if (update) {
            setTimeout(() => {
              // this.chartsChangeData();
              // this.sendBusEvent('bus', 'chartResize', '');
              resolve(true);
            }, 0);
          } else {
            resolve(true);
          }
        }, 0);
      } else {
        resolve(false);
      }
    });
  }

  private sendBusEvent(type: 'bus' | 'mbus', key: string, ...val: any) {
    const newEventName: string = this.GT_editor.getRegEventName('send', key);
    const eventName = newEventName ?? key;
    if (type === 'bus') {
      Tsrv.reliablySendingBusEvent(eventName, this.$bus, 10, 100, ...val);
    } else {
      Tsrv.reliablySendingBusEvent(eventName, this.$mbus, 10, 100, ...val);
    }
  }

  private setHeaderGroup(config: any) {
    this.headerGroup = [];
    if (Tsrv.utils.isArray(config)) {
      this.headerGroup = config;
    }
  }

  private setRules(config: any) {
    this.rowStyleCfg = [];
    this.columnStyleCfg = [];
    this.cellStyleCfg = [];
    // if (config !== null && config) {
    if (!Tsrv.noValue(config) && Array.isArray(config)) {
      config.forEach(el => {
        if (
          !Tsrv.noValues(el?.results, el?.conditions) &&
          Array.isArray(el?.results) &&
          Array.isArray(el?.conditions)
        ) {
          el.results.forEach(result => {
            if (result?.type === 'row') {
              const style = {};
              if (result?.backColor !== '')
                // style['backgroundColor'] = `${result.backColor} !important`;
                style['backgroundColor'] = `${result.backColor}`;
              if (result?.fontColor !== '') style['color'] = result.fontColor;
              if (result?.fontWeight === true) style['fontWeight'] = 'bold';
              if (result?.fontStyle === true) style['fontStyle'] = 'italic';
              if (result?.fontDec === true)
                style['textDecoration'] = 'underline';
              this.rowStyleCfg.push({
                style,
                conditions: el.conditions
              });

              if (!!result?.isDisable || !!result?.isEditable) {
                this.rowEditCfg.push({
                  editable: !result?.isDisable,
                  conditions: el.conditions
                });
              }
            } else if (result?.type === 'column') {
              if (!Tsrv.utils.isEmpty(result?.field)) {
                const style = {};
                if (result?.backColor !== '')
                  style['backgroundColor'] = `${result.backColor} !important`;
                if (result?.fontColor !== '') style['color'] = result.fontColor;
                if (result?.fontWeight === true) style['fontWeight'] = 'bold';
                if (result?.fontStyle === true) style['fontStyle'] = 'italic';
                if (result?.fontDec === true)
                  style['textDecoration'] = 'underline';
                this.columnStyleCfg.push({
                  field: result.field,
                  style,
                  conditions: el.conditions
                });

                if (!!result?.isDisable || !!result?.isEditable) {
                  this.columnEditCfg.push({
                    field: result.field,
                    editable: !result?.isDisable,
                    conditions: el.conditions
                  });
                }
              }
            } else if (result?.type === 'cell') {
              if (!Tsrv.utils.isEmpty(result?.field)) {
                const style = {};
                if (result?.backColor !== '')
                  style['backgroundColor'] = `${result.backColor} !important`;
                if (result?.fontColor !== '') style['color'] = result.fontColor;
                if (result?.fontWeight === true) style['fontWeight'] = 'bold';
                if (result?.fontStyle === true) style['fontStyle'] = 'italic';
                if (result?.fontDec === true)
                  style['textDecoration'] = 'underline';
                this.cellStyleCfg.push({
                  field: result.field,
                  style,
                  conditions: el.conditions
                });

                if (!!result?.isDisable || !!result?.isEditable) {
                  this.cellEditCfg.push({
                    field: result.field,
                    editable: !result?.isDisable,
                    conditions: el.conditions
                  });
                }
              }
            }
          });
        }
      });
    }
  }

  private cellStyle({ row, rowIndex, column, columnIndex }) {
    let style = null;
    if (!Tsrv.utils.isEmpty(this.columnStyleCfg)) {
      for (let i = 0; i < this.columnStyleCfg.length; i++) {
        if (this.columnStyleCfg[i].field === column.property) {
          if (
            vxeConfig.grid.verifyRules(row, this.columnStyleCfg[i].conditions)
          ) {
            style = this.columnStyleCfg[i].style;
            break;
          }
        }
      }
    }

    if (!Tsrv.utils.isEmpty(this.rowStyleCfg)) {
      for (let i = 0; i < this.rowStyleCfg.length; i++) {
        if (vxeConfig.grid.verifyRules(row, this.rowStyleCfg[i].conditions)) {
          style = this.rowStyleCfg[i].style;
          break;
        }
      }
    }

    if (!Tsrv.utils.isEmpty(this.cellStyleCfg) && column.property) {
      for (let i = 0; i < this.cellStyleCfg.length; i++) {
        const columnName =
          column.property.indexOf('|') > -1
            ? column.property.split('|')[1]
            : column.property;
        if (this.cellStyleCfg[i].field === columnName) {
          if (
            vxeConfig.grid.verifyRules(row, this.cellStyleCfg[i].conditions)
          ) {
            style = this.cellStyleCfg[i].style;
            break;
          }
        }
      }
    }
    return style;
  }

  /**
   * @description 行样式设置规则
   * @description 应用不多，现只简易结构
   */
  private rowStyle({ row, rowIndex, $rowIndex }) {
    let style = null;
    if (
      Tsrv.noValue(this.parentName) &&
      !Tsrv.noValue(row?._audited_) &&
      row?._status_ !== 0
    ) {
      style = {
        backgroundColor: '#DFE5E6',
        cursor: 'not-allowed'
      };
    }
    return style;
  }

  public setToolbar(toolbar: any) {
    this.toolbar = vxeConfig.getToolbarConfig(toolbar, 'basegrid');
    if (toolbar === false) {
      this.defaultToolbar = false;
    } else {
      this.defaultToolbar = this.defaultToolbar;
      this.toolbar.delete.isDisable = true;
    }
  }

  public setToolbarConf(display: any) {
    if (!Tsrv.noValue(display)) {
      if (!Tsrv.noValue(display?.left)) {
        display.left = !!display?.left;
      }
      if (!Tsrv.noValue(display?.right)) {
        display.right = !!display?.right;
      }
      if (display.left || display.right) {
        const toolbar = this.GT_editor.getToolbar();
        toolbar.handleToolbarDisplay(display);
      } else {
        const style = {
          showToolbar: false
        };
        this.setStyle(style);
      }
    }
  }

  private setFunI18nFields(funI18nFields: Array<any>) {
    if (!Tsrv.noValue(funI18nFields)) {
      this.funI18nFields = funI18nFields;
    }
  }

  /**
   * handleListener 监听事件
   */
  private handleListener(msg: any) {
    switch (msg.type) {
      case 'search':
        this.handleResponseSearch(msg);
        break;
      case 'refresh':
        this.commitEvent('refresh');
        break;

      case 'requestSendSelect':
        this.sendSelection(msg); // 请求发送数据
        break;
      case 'custBtnRequestSend':
        this.custBtnRequestSend(msg); // 请求发送数据
        break;
      case 'requestChangeNextRow':
        this.requestChangeNextRow();
        break;
      case 'requestChangePrevRow':
        this.requestChangePrevRow();
        break;
      case 'requestSearch':
        this.handleRequstSearch(msg.val);
        break;
      case 'requestFilter':
        this.handleRequstFilter(msg.val);
        break;
      // 组件协调事件
      case 'coordination':
        this.GT_editor.receEventCoordination(msg);
        break;
      default:
    }
  }

  private requestChangePrevRow() {
    const next = this.getPrevRow();
    if (next) {
      const index = this.GT_editor.getGrid().getRowIndex(next);
      this.GT_editor.getGrid().setCurrentRow(next);
      this.setCurrentRow(next, index);
    }
  }

  private requestChangeNextRow() {
    const next = this.getNextRow();
    if (next) {
      const index = this.GT_editor.getGrid().getRowIndex(next);
      this.GT_editor.getGrid().setCurrentRow(next);
      this.setCurrentRow(next, index);
    }
  }

  public handleRequstFilter(cfg: any) {
    cfg.forEach(el => {
      this.addFilter(el.field, el.value);
    });
    this.GT_editor.loadTableData();
  }

  private handleResponseSearch(m: any) {
    const msg = Tsrv.utils.clone(m, true);
    // "联查搜索" 事件 回调
    this.GT_editor.searchFilterChange(msg);

    if (msg.option) {
      this.currentRowData['msg'] = msg; //------
      if (msg.option.autoCompleteInfo) {
        this.setAutoComplete(msg.option.autoCompleteInfo);
        this.setLinkParent(msg.option.autoCompleteInfo);
      }
    }
    // if (msg.content.val[0] === null) {
    //   msg.content.val[0] = '-1';
    // }
    if (Tsrv.utils.noValue(msg.content.val[0])) {
      msg.content.val[0] = '-1';
      this.setToolbarStatus('insert', 'isDisable', true);
    } else {
      this.setToolbarStatus('insert', 'isDisable', false);
    }
    if (Tsrv.utils.noValue(msg?.content?.where)) {
      msg.content['where'] = {};
      if (!Tsrv.utils.noValue(msg?.content?.val)) {
        msg.content.where = {
          [msg.content.ukey]: { $in: msg.content.val }
        };
        if (
          !Tsrv.utils.noValue(
            msg.content.fliter && msg.content.fliter === 'range'
          )
        ) {
          msg.content.where = {
            [msg.content.ukey]: {
              $and: [{ $gte: msg.content.val[0] }, { $lte: msg.content.val[1] }]
            }
          };
        }
      }
    }

    if (this.pagerConfig) {
      this.tablePage.currentPage = 1;
    }
    this.seqStartIndex = 0;
    const filter = new ts.T_filter();
    if (!Tsrv.utils.noValue(msg.content?.where)) {
      filter.filter = msg.content.where;
      this.GT_editor.addInitFilter(filter);
      this.GT_editor.setScope(msg.content.ukey, msg.content.val[0]);
      this.GT_editor.loadTableData();
    } else {
      this.clearTableData();
    }
  }

  private handleRequstSearch(cfg: any) {
    if (cfg.initSearch && cfg.initSearch !== '') {
      // this.GT_editor.addInitFilter(cfg.initSearch);
      this.GT_editor.setInjectFilter(cfg.initSearch);
    }

    if (cfg.globalSearch && cfg.globalSearch !== '') {
      this.globalSearch(cfg.globalSearch);
    } else {
      this.GT_editor.loadTableData();
    }
  }

  /**
   * handleCurrentRowChange 选中行变动
   * {newValue, oldValue, row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }
   */
  private handleCurrentRowChange(val: any) {
    if (this.isShift) {
      val.$event.preventDefault();
      val.$event.stopPropagation();

      const fromIndex = Math.min(val.rowIndex, this.current.rowIndex);
      const toIndex = Math.max(val.rowIndex, this.current.rowIndex);
      const data = val.$table.getTableData().visibleData;
      for (let i = fromIndex; i <= toIndex; i++) {
        if (data[i]) {
          this.GT_editor.getGrid().setCheckboxRow(
            data[i],
            !this.GT_editor.getGrid().isCheckedByCheckboxRow(data[i])
          );
        }
      }

      window.getSelection().removeAllRanges();
    }

    this.setCurrentRow(val.row, val.$rowIndex);
  }

  private openUploadFile(value: any, row: any) {
    Tsrv.utils
      .createModal('o-file-manager', {
        limit: 100,
        upload: [],
        selected: Tsrv.utils.clone(value.fileList, true),
        action: value.fileList.length > 0 ? 'default' : 'file',
        hasCurrent: true
      })
      .then(data => {
        if (data) {
          const list = {
            fileList: data
          };
          row._file_ = Tsrv.utils.toJSONString(list);
          this.updateSaveBtnStatus();
        }
      });
  }

  /**
   * checkboxChange checkbox变化
   */
  private checkboxChange(e: any) {
    this.GT_editor.setCustBtnStatusByRowChk();
    if (this.toolbar !== null) {
      // 获取选择项
      const records = this.GT_editor.getGrid().getCheckboxRecords();
      let length = 0;
      if (records) {
        length = records.length;
      }
      // 删除按钮更新
      this.toolbar.delete && (this.toolbar.delete.isDisable = length === 0);
      if (length > 0) {
        // 新版 审核/审批业务 相关按钮联动
        let auditStatus;
        let billStatus;
        let statusIsSame = true;
        for (let i = 0; i < length; i++) {
          if (
            records[i]['_audited_'] !== undefined &&
            records[i]['_status_'] !== undefined &&
            records[i].id !== null
          ) {
            if (auditStatus === undefined && billStatus === undefined) {
              // auditType = status;
              auditStatus = records[i]['_audited_'];
              billStatus = records[i]['_status_'];
            } else {
              if (
                auditStatus !== records[i]['_audited_'] ||
                billStatus !== records[i]['_status_']
              ) {
                statusIsSame = false;
                break;
              }
            }
          } else {
            statusIsSame = false;
          }
        }
        this.toolbar.audit && (this.toolbar.audit.value = auditStatus === 1);
        this.toolbar.requestAudit &&
          (this.toolbar.requestAudit.value =
            auditStatus === 1 && billStatus === 101);
        this.toolbar.accountPosted &&
          (this.toolbar.accountPosted.value = billStatus === 200);
        this.toolbar.caseclosed &&
          (this.toolbar.caseclosed.value = billStatus === 300);
        this.toolbar.freeze && (this.toolbar.freeze.value = billStatus === 999);
        if (statusIsSame) {
          if (!Tsrv.noValues(this.toolbar.audit, this.toolbar.unaudit)) {
            if (auditStatus === 1) {
              this.toolbar.audit.value = true;
              this.toolbar.unaudit.auth = true;
              // 审核相关按钮 状态
              this.toolbar.audit.isDisable = !(
                billStatus === 0 || billStatus === 101
              );
            } else {
              this.toolbar.audit.value = false;
              // 审核相关按钮 状态
              this.toolbar.audit.isDisable = !(
                billStatus === 0 || billStatus === 101
              );
            }
          }
          this.toolbar.requestAudit &&
            (this.toolbar.requestAudit.isDisable = !(
              (auditStatus === 0 && billStatus === 0) ||
              (auditStatus === 1 && billStatus === 101)
            ));
          this.toolbar.auditStatus &&
            (this.toolbar.auditStatus.isDisable = !(
              auditStatus === 0 && billStatus === 100
            ));
          this.toolbar.accountPosted &&
            (this.toolbar.accountPosted.isDisable = !(
              auditStatus === 1 &&
              (billStatus === 101 || billStatus === 200)
            ));
          this.toolbar.caseclosed &&
            (this.toolbar.caseclosed.isDisable = !(
              auditStatus === 1 &&
              (billStatus === 101 || billStatus === 200 || billStatus === 300)
            ));
          this.toolbar.freeze &&
            (this.toolbar.freeze.isDisable =
              billStatus === -1 || billStatus === 200 || billStatus === 300);
          this.toolbar.void &&
            (this.toolbar.void.isDisable =
              billStatus >= 200 || billStatus === -1);
          // 根据 单据审核状态 决定 除审核相关的标准按钮 状态
          if (auditStatus === 1 || billStatus !== 0) {
            // this.toolbar.edit.isDisable = true;
            this.toolbar.delete && (this.toolbar.delete.isDisable = true);
          }
        } else {
          this.GT_editor.requestAuditBtnStatus('isDisable', true);
        }
      } else {
        this.GT_editor.requestAuditBtnStatus('isDisable', true);
      }
      //
      if (e) {
        if (e.row) {
          if (e.checked === true && e.row.id) {
            this.addStoredSelection(e.row);
          } else if (e.checked === false && e.row.id) {
            this.removeStoredSelection(e.row);
          }
        } else if (e.selection) {
          if (e.checked) {
            e.selection.forEach(el => {
              this.addStoredSelection(el);
            });
          } else {
            e.$table.getData().forEach(el => {
              this.removeStoredSelection(el);
            });
          }
        } else {
          if (e.checked) {
            e.records.forEach((item, index) => {
              this.addStoredSelection(item);
            });
          } else if (e.checked) {
            e.records.forEach((item, index) => {
              this.removeStoredSelection(item);
            });
          }
        }
      }
      this.handleSelectionChange(e);
    }
  }

  private addStoredSelection(row: any) {
    const find = Tsrv.utils.find(this.storedSelection, el => el.id === row.id);
    if (!find) {
      this.storedSelection.push(Tsrv.utils.clone(row, true));
    }
  }

  private removeStoredSelection(row: any) {
    const find = Tsrv.utils.find(this.storedSelection, el => el.id === row.id);
    if (find) {
      Tsrv.utils.remove(this.storedSelection, el => el.id === row.id);
    }
  }

  // 表格数据 checkbox 选中数据改变时处理
  private handleSelectionChange(e: any) {
    //  this.storedSelection
    // const records = this.GT_editor.getGrid().getCheckboxRecords();
    const pubApiNane = this.GT_editor.getActionCfg()?.rowSelected;
    //  选中事件
    if (e && e.checked && e?.row && pubApiNane) {
      const params = this.GT_editor.getSelectedData('select');
      params.title = pubApiNane;
      params.from = 'rowSelected';
      params['currentRow'] = e.row;
      this.GT_editor.doEvent(pubApiNane, params);
    }
  }

  /**
   * handleCellClick 单元格点击
   */
  private handleCellClick(e) {
    // this.GT_editor.setCurrRowIdx(e.rowIndex);
    //  加编辑锁
    if (this.isUseEditLock && this.isEditable) {
      if (this.GT_editor.editLocked.has(e.row.id)) {
        this.$msg('214,FE,11,Data locked');
      }
      if (!this.GT_editor.editLockNum.has(e.row.id)) {
        this.GT_editor.handleEditLock(e.row, 'lock');
      }
    }

    this.current.cell = {};
    this.current.columnIndex = this.getColumnIndex(e.column);
    this.current.column = e.column;
    if (this.isCtrl) {
      this.GT_editor.getGrid().setCheckboxRow(
        e.row,
        !this.GT_editor.getGrid().isCheckedByCheckboxRow(e.row)
      );
    }
    if (this.isShift) {
      if (!this.GT_editor.getGrid().isCheckedByCheckboxRow(this.current.row)) {
        this.GT_editor.getGrid().setCheckboxRow(e.row, true);
      }
    }
  }

  /**
   * 单元格双击
   */
  private handleCellDBLClick(ev) {
    // const params = {
    //   funName: this.funName,
    //   from: 'rowDbClick',
    //   data: {},
    //   parentID: this.linkParent.rowID || 0,
    // };
    // params.data[this.tableName] = [ev.row.id];
    // this.GT_editor.doEvent('_sys_interaction_default_resp', params);
    // return;
    //
    if (this.listenType === 'magicbox') {
      if (ev.row.id !== null) {
        this.GT_editor.getGrid().setCheckboxRow(ev.row, true);
        this.storedSelection = [Tsrv.utils.clone(ev.row, true)];
        // 执行上层容器oMagicBox提交数据
        this.okMagicBox();
      }
    } else if (
      // this.editStatus && this.isEditable
      Tsrv.getx(this._config, 'triggerEvent.rowDbClick', false) &&
      ev.column.type !== 'checkbox'
    ) {
      this.showRowEditor(ev);
    }
    if (!this.isIndependent) {
      this.$emit('on-row-dbclick', {
        index: this.parentID,
        data: ev,
        eventType: 'row-dbclick',
        funName: this.GT_editor.getFunName(),
        tableName: this.GT_editor.getTableName()
      });
    }
    // 无报表组件
    if (
      this.listenType === 'default' &&
      !Tsrv.utils.isEmpty(this.toolbar?.queryLink)
    ) {
      this.queryLinkClick(0, ev.data.row);
    }
    // 将事件抛出
    this.$emit(`on-cell-dblclick`, Tsrv.utils.clone(ev));
  }

  private showRowEditor(ev?: any) {
    const isNew = Tsrv.noValue(ev);
    if (this.tableType === 'basegrid') {
      this.columnEditModal.config = this._config?.triggerEvent ?? null;
      this.columnEditModal.editStatus = isNew
        ? 'new'
        : this.GT_editor.editorStatus;
      if (isNew) {
        const custEv = { row: null };
        this.getInsertInitData().then(initData => {
          custEv.row = initData;
          this.currentRowData = {
            config: this._config,
            ev: custEv
          };
          this.columnEditModal.isShow = true;
        });
      } else {
        this.currentRowData = {
          config: this._config,
          ev
        };
        this.columnEditModal.isShow = true;
      }
    } else if (this.tableType === 'baseview') {
      // 整理传参（获取页码的存储过程所需参数）
      const params = {
        funName: this.funName,
        from: 'rowDbClick',
        data: {},
        parentID: this.linkParent.rowID || 0
      };
      params.data[this.tableName] = [ev?.row?.id];
      this.GT_editor.doEvent(Tsrv.globalVar.spName.jumpToFun, params);
    }
  }

  private getInsertInitData(): Promise<any> {
    return new Promise((resolve, reject) => {
      const fields = this.GT_editor.getFields();
      const row: any = {};
      fields.forEach(k => {
        row[k] = null;
      });
      // m2o，slc，pid默认值插入
      fields.forEach(key => {
        if (this.m2oSetting[key] !== undefined) {
          row[key] = this.m2oSetting[key]; // 设置对应字段
          const realField: string = vxeConfig.grid.getRealField(key);
          row[realField] = this.m2oSetting[realField]; // 设置原字段
        }
        if (this.slcSetting[key] !== undefined) {
          row[key] = this.slcSetting[key]; // 设置对应字段
        }
        if (this.pidSetting[key] !== undefined) {
          row[key] = this.pidSetting[key];
        }
        if (key === 'id') {
          row[key] = Tsrv.getSnowIDFmtStr();
        }
        if (!Tsrv.utils.noValue(this.linkParent.defaultVal)) {
          for (const f of this.linkParent.defaultVal) {
            if (f.field === key) {
              row[key] = f.value;
              break;
            }
          }
        }
      });

      const TdevVal = new ts.T_defVal();
      TdevVal.setLang(this.$i18n.locale)
        .setDbType('mysql')
        .setFunName(this.GT_editor.getFunName());
      TdevVal.setMainfunName(this.linkParent.mainFunName).setRowID(
        this.linkParent.rowID
      );
      Tsrv.getDefaultVal(TdevVal)
        .then(fvs => {
          fvs.forEach(fv => {
            if (fields.has(fv.field)) {
              row[fv.field] = fv.value;
            }
          });
          resolve(row);
        })
        .catch(r => {
          throw new Error(r);
        });
    });
  }

  /**
   * row改变
   */
  private rowEditChange(type: string, change?: any) {
    // const changes = this.getChanges();
    const changes = {
      insertRecords: [],
      updateRecords: [],
      removeRecords: []
    };
    if (type === 'close') {
      this.commitEvent('refresh');
    } else if (type === 'delete') {
      this.GT_editor.getGrid().setCheckboxRow(change, true);
      this.commitEvent('delete');
    } else {
      // if (type === 'modify') {
      //   const idField = change.find(item => item.field === 'id');
      //   if (!Tsrv.noValue(idField)) {
      //     if (idField.value === -1) {
      //       idField.value = Tsrv.getSnowIDFmtStr();
      //       // change.splice(change.length - 1, 1);
      //       changes.insertRecords.push(change);
      //     } else {
      //       changes.updateRecords.push(change);
      //     }
      //   }
      // }
      if (type === 'modify') {
        changes.updateRecords.push(change);
      } else if (type === 'insert') {
        changes.insertRecords.push(change);
      }
      this.GT_editor.doSave(changes)
        .then(() => {
          this.GT_editor.sendEventCoordination('save');
          this.GT_editor.unLockALL();
        })
        .catch(r => {
          this.initTableStatus();
        });
    }
  }

  /**
   * 设置当前row
   */
  private setCurrentRow(row: any, rowIndex?: number) {
    this.$emit('on-row-change', {
      index: this.parentID,
      data: {
        from: {
          rowIndex: this.current.rowIndex,
          row: this.current.row
        },
        to: {
          rowIndex,
          row
        }
      }
    });
    this.current.row = row;
    this.current.rowIndex = rowIndex;
    this.messageEmit('search', [row]);
  }

  /**
   * 获取下一行
   */
  private getNextRow(): any {
    const data = this.GT_editor.getGrid().getTableData().visibleData;
    const totalRowLength = data.length;
    if (this.current.rowIndex + 1 < totalRowLength) {
      return data[this.current.rowIndex + 1];
    }
    return false;
  }

  /**
   * 获取行
   */
  private getRow(data: any, offset: number): any {
    const totalRowLength = data.length;
    if (
      this.current.rowIndex + offset < totalRowLength &&
      this.current.rowIndex + offset >= 0
    ) {
      return data[this.current.rowIndex + offset];
    }
    return false;
  }

  /**
   * 获取上一行
   */
  private getPrevRow(): any {
    const data = this.GT_editor.getGrid().getTableData().visibleData;
    if (this.current.rowIndex !== 0) {
      return data[this.current.rowIndex - 1];
    }
    return false;
  }

  private updateSaveBtnStatus() {
    if (this.toolbar && !this.toolbar.audit.value) {
      const changes = this.getChanges();
      this.toolbar.save &&
        (this.toolbar.save.isDisable =
          changes.removeRecords.length === 0 &&
          changes.updateRecords.length === 0 &&
          changes.insertRecords.length === 0);
    }
  }

  /**
   * listenDoChange 值确定改变时，请求action
   */
  private listenDoChange(e: any) {
    this.updateSaveBtnStatus();
    if (this.isIndependent) {
      let action;
      if (e.column.editRender.attrs['actions']) {
        action = e.column.editRender.attrs['actions'].dochange;
      }
      if (action) {
        const params = {
          pFuncName: Tsrv.globalVar.spName.apiVceSpName,
          pCalcField: e.column.property,
          pData: [
            {
              sTableName: this.GT_editor.getTableName(),
              sFuncName: this.GT_editor.getFunName(),
              iCalcTable: 1,
              sTableData: e.row
            }
          ]
        };
        Tsrv.httpReqV1.vce(params).then(res => {
          res = res.data;
          if (res.success) {
            const fullData = this.GT_editor.getGrid().getTableData().fullData;
            Object.keys(res.data.data).forEach(key => {
              if (key.indexOf('.') > -1) {
                const field = key.split('.')[1];
                for (let i = 0; i < fullData.length; i++) {
                  if (fullData[i]._XID === e.row._XID) {
                    fullData[i][field] = res.data.data[key];
                    break;
                  }
                }
              }
            });
          }
        });
      }
    } else {
      this.$emit('on-change', {
        index: this.parentID,
        data: e,
        eventType: 'dochange',
        funName: this.GT_editor.getFunName(),
        tableName: this.GT_editor.getTableName()
      });
    }
  }

  /**
   * listenKeyUp
   */
  private listenKeyUp() {
    this.isCtrl = false;
    this.isShift = false;
    this.isAlt = false;
    this.userSelect = 'text';
    window.removeEventListener('keyup', this.listenKeyUp);
  }

  private getColumnIndex(e: any) {
    const visibleColumns = this.GT_editor.getGrid().getTableColumn()
      .visibleColumn;
    const property = e.property;
    for (let i = 0; i < visibleColumns.length; i++) {
      if (visibleColumns[i].field === property) {
        return i;
      }
    }
    return -1;
  }

  private getPrevActiveColumn(columnIndex: number) {
    const nextColumn: any = this.GT_editor.getGrid().getColumns(columnIndex);
    if (nextColumn) {
      const current = Tsrv.utils.clone(this.current, true);
      current.column = nextColumn;
      current.columnIndex = columnIndex;
      if (this.beforeEditMethod(current) && nextColumn.property) {
        return nextColumn;
      }
      return this.getPrevActiveColumn(columnIndex - 1);
    }
    return null;
  }

  private getNextActiveColumn(columnIndex: number) {
    const nextColumn: any = this.GT_editor.getGrid().getColumns(columnIndex);
    if (nextColumn) {
      const current = Tsrv.utils.clone(this.current, true);
      current.column = nextColumn;
      current.columnIndex = columnIndex;
      if (
        this.beforeEditMethod(current) &&
        nextColumn.property &&
        nextColumn.property !== 'id' &&
        nextColumn.editRender &&
        nextColumn.editRender.name !== 'oSwitch'
      ) {
        return nextColumn;
      }
      return this.getNextActiveColumn(columnIndex + 1);
    }
    return null;
  }

  private setActiveRow(row: any) {
    const nextColumn = this.getNextActiveColumn(0);
    if (nextColumn) {
      // 如果有下一行，则跳转
      this.GT_editor.getGrid().setEditCell(row, nextColumn.property);
    }
  }

  /**
   * listenKeyDown 按键监听
   */
  private listenKeyDown(e: any) {
    if (e.$event.target.name !== 'global') {
      window.addEventListener('keyup', this.listenKeyUp);
      this.$emit('on-change', {
        index: this.parentID,
        data: e,
        eventType: 'input'
      });
      const code = e.$event.key;
      const ctrl = e.$event.ctrlKey;
      const alt = e.$event.altKey;
      const shift = e.$event.shiftKey;
      const val = e.$event.target.value;
      this.isCtrl = ctrl || code === 'Meta';
      this.isShift = shift;
      this.isAlt = alt;
      if (this.isShift) this.userSelect = 'none';
      if (this.isHotKeyActive) {
        const keyArr = [
          'Tab',
          'Enter',
          '1',
          '2',
          '3',
          '4',
          'ArrowUp',
          'ArrowDown'
        ];
        // 如果输入内容为空，则代理箭头
        if (val === '' || val === null || e.$event.target.nodeName === 'BODY') {
          keyArr.push('ArrowRight', 'ArrowLeft');
        }
        if (keyArr.indexOf(code) > -1) {
          let nextRow;
          let prevRow;
          let nextColumn;
          let prevColumn;
          if (
            code === 'Tab' ||
            (code === 'Enter' && !ctrl) ||
            code === 'ArrowRight'
          ) {
            // tab/enter/右箭头
            e.$event.preventDefault();
            nextColumn = this.getNextActiveColumn(this.current.columnIndex + 1);
            if (nextColumn) {
              // 如果有下一行，则跳转
              this.GT_editor.getGrid().setActiveCell(
                this.current.row,
                nextColumn.property
              );
            } else {
              // 如果没有下一行，则插入
              nextRow = this.getNextRow();
              if (nextRow) this.setActiveRow(nextRow);
              else this.insertRow(-1, { active: true });
            }
          } else if (code === 'ArrowLeft') {
            // 左箭头
            e.$event.preventDefault();
            prevColumn = this.getPrevActiveColumn(this.current.columnIndex - 1);
            if (prevColumn) {
              this.GT_editor.getGrid().setActiveCell(
                this.current.row,
                prevColumn.property
              );
            }
          } else if (code === 'ArrowUp') {
            // 上箭头
            e.$event.preventDefault();
            prevRow = this.getPrevRow();
            if (prevRow)
              this.GT_editor.getGrid().setEditCell(
                prevRow,
                this.current.column.property
              );
            else this.insertRow(null);
          } else if (code === 'ArrowDown' || (code === 'Enter' && ctrl)) {
            // 下箭头/ctrl+enter
            e.$event.preventDefault();
            nextRow = this.getNextRow();
            if (nextRow)
              this.GT_editor.getGrid().setEditCell(
                nextRow,
                this.current.column.property
              );
            else this.insertRow(-1);
          } else if (code === '1' && alt) {
            // alt + 1
            e.$event.preventDefault();
            this.insertRow(this.current.row);
          } else if (code === '2' && alt) {
            // alt + 2
            e.$event.preventDefault();
            const tableData = this.GT_editor.getGrid().getTableData();
            if (tableData.visibleData[this.current.rowIndex + 1]) {
              this.insertRow(tableData.visibleData[this.current.rowIndex + 1]);
            } else {
              this.insertRow(-1);
            }
          } else if (code === '3' && alt) {
            // alt + 3
            e.$event.preventDefault();
            this.insertRow(null);
          } else if (code === '4' && alt) {
            // alt + 4
            e.$event.preventDefault();
            this.insertRow(-1);
          }
        }
      } else if (!this.isHotKeyActive && this.current.cell !== null) {
        if (!ctrl) {
          this.GT_editor.getGrid().setActiveCell(
            this.current.row,
            this.current.column.property
          );
        }
      }
      // ctrl + ~ 键 （切换basegrid展示模式————table-or-graph）
      if (code === '`' && alt) {
        this.switchModel();
      }
    }
  }

  /**
   * listenPaste 粘贴监听
   */
  private listenPaste(e: any) {
    if (this.current.cell !== null) {
      // 获取剪切板数据
      const data = e.clipboardData;
      const text = data.getData('text/plain');

      // 辨别数据类型
      if (Tsrv.utils.isJSONString(text)) {
        // 如果为json，则为行数据
        const textObj = JSON.parse(text);
        if (Tsrv.utils.isPlainObject(textObj)) {
          e.preventDefault();

          Object.keys(textObj).forEach(key => {
            // 2.0废弃了GUID
            if (this.current.row[key] !== undefined && key !== 'FGUID') {
              this.current.row[key] = textObj[key];
            }
          });
        }
        this.updateSaveBtnStatus();
        if (!this.isIndependent) {
          this.$emit('on-change', {
            index: this.parentID,
            data: e,
            eventType: 'dochange',
            funName: this.GT_editor.getFunName(),
            tableName: this.GT_editor.getTableName()
          });
        }
      } else if (text.indexOf('\t') > -1 || text.indexOf('\n') > -1) {
        // 如果为excel数据
        e.preventDefault();

        // 分隔数据到数组
        let rows = [];
        if (text.indexOf('\n') > -1) {
          rows = text.split('\n');
          rows.pop();
        } else {
          rows[0] = text;
        }
        rows = rows.map(el => {
          if (el.indexOf('\t') > -1) return el.split('\t');
          return [el];
        });

        // 遍历插入
        const P_data = this.GT_editor.getGrid().getTableData().visibleData;
        for (let i = 0; i < rows.length; i++) {
          const nextRow = this.getRow(P_data, i);
          if (nextRow) {
            for (let s = 0; s < rows[i].length; s++) {
              const nextColumn: any = this.GT_editor.getGrid().getColumns(
                this.current.columnIndex + s
              );

              if (nextColumn) {
                nextRow[nextColumn.property] = rows[i][s].trim();
                if (nextColumn.editRender.name === 'oNumberInput') {
                  rows[i][s].trim() === '' &&
                    (nextRow[nextColumn.property] = null);
                }
              } else {
                break;
              }
            }
            // 验证数据
            this.GT_editor.getGrid().validate(nextRow, res => {
              for (const key in res) {
                res[key]['row'][key] = null;
              }
            });
          } else {
            break;
          }
        }
        this.updateSaveBtnStatus();
        if (!this.isIndependent) {
          this.$emit('on-change', {
            index: this.parentID,
            data: e,
            eventType: 'dochange',
            funName: this.GT_editor.getFunName(),
            tableName: this.GT_editor.getTableName()
          });
        }
      }
    }
  }

  public validate(rows?: any) {
    return rows
      ? this.GT_editor.getGrid().validate(rows)
      : this.GT_editor.getGrid().fullValidate();
  }

  /**
   * listenBlur 失去焦点监听
   */
  private listenBlur(e: any) {
    this.isHotKeyActive = false;
    this.current.cell = null;
    this.$emit('on-change', {
      index: this.parentID,
      data: e,
      eventType: 'blur'
    });

    // window.removeEventListener('paste', this.listenPaste);
  }

  /**
   * listenFocus 获得焦点监听
   */
  private listenFocus(e: any) {
    this.isHotKeyActive = true;
    this.current.row = e.row;
    this.current.rowIndex =
      e.rowIndex === -1
        ? Tsrv.utils.findIndexOf(
            e.$table.getTableData().visibleData,
            // eslint-disable-next-line eqeqeq
            el => el._XID == e.row._XID
          )
        : e.rowIndex;
    this.current.columnIndex = this.getColumnIndex(e.column);
    this.current.column = e.column;
    this.current.cell = e.cell;
    this.$emit('on-change', {
      index: this.parentID,
      data: e,
      eventType: 'focus'
    });
    // window.addEventListener('paste', this.listenPaste);
  }

  // 通过事件toID获取要search的功能名
  private getFunNameByToID(toID: string): string {
    for (const o of this._config.messageConfig.emitActions.search) {
      if (o.toID !== toID) {
        continue;
      } else {
        return o.sourceToID;
      }
    }
    return '';
  }

  /**
   * messageEmit 发送外部事件，信号中转站
   */
  //
  private messageEmit(type: any, row: any = null) {
    // if (Tsrv.utils.noValue(row)) {
    //   this.setToolbarStatus('insert', 'isDisable', true);
    // } else {
    //   this.setToolbarStatus('insert', 'isDisable', false);
    // }
    if (this.messageConfig !== null) {
      // 获取所有收信人
      const receivers = this.messageConfig.emitActions[type] || [];

      receivers.forEach((item: any) => {
        item.msg.listenType = this.listenType;
        // 发出的是search信号/refresh信号
        if (type === 'search') {
          // 装填搜索key对应的值
          item.msg.content.val = Tsrv.utils.map(
            row,
            el => el[item.msg.content.ikey]
          );
          if (item.msg.content.val.indexOf(undefined) < 0) {
            const toID = item.toID.toString();
            // option
            if (item.msg.content.val.length === 1) {
              const option = {
                autoCompleteInfo: {
                  key: item.msg.content.val[0],
                  sourceToID: toID,
                  toTable: this.getFunNameByToID(toID),
                  table: this.GT_editor.getTableName(), // 表与表对应设置M2o  表与表之间是来源表的意思 fromTable
                  data: row[0]
                }
              };
              item.msg['option'] = option;
            }
            // 发出
            if (this.listenType === 'default') {
              this.sendBusEvent('bus', toID, item.msg);
            } else {
              this.sendBusEvent('mbus', toID, item.msg);
            }
          }
        } else if (type === 'refresh') {
          const toID = item.toID.toString();
          // refresh信号直接发出
          if (this.listenType === 'default') {
            this.sendBusEvent('bus', toID, item.msg);
          } else {
            this.sendBusEvent('mbus', toID, item.msg);
          }
        }
      });
    }
  }

  public setColumns(columns: any, isRaw: boolean = false) {
    let tableColumns = Tsrv.utils.clone(columns, true);
    if (isRaw) {
      tableColumns = this.transformColumns(tableColumns);
    } else {
      tableColumns.unshift({
        field: 'id',
        title: 'ID',
        width: '50',
        align: 'center',
        visible: false,
        editRender: {
          name: 'oIdRender'
        }
      });
      // tableColumns.unshift({
      //   title: '#',
      //   width: '50',
      //   align: 'center'
      // ,
      // params: {
      //   openFileManager: this.openFileManager
      // }
      // ,
      // editRender: {
      //   name: 'oSeqRender'
      // }
      // });
      tableColumns.unshift({
        type: 'seq',
        width: '50',
        align: 'center'
      });
      tableColumns.unshift({
        type: 'checkbox',
        width: '50',
        align: 'center',
        visible: true,
        fixed: 'left'
      });
    }
    this.GT_editor.getGrid().loadColumn(tableColumns);
    this.tableColumns = tableColumns;
  }

  private setColumnsGroup(columns: any) {
    if (this.headerGroup.length > 0 && columns.length > 0) {
      const ifFind = (test, value) => {
        if (value === test) {
          return true;
        }
        if (test.indexOf(`|${value}|`) > -1) {
          return true;
        }
        return false;
      };

      // 创建二级分组
      const level3Pool = [];
      const level3Group = {};
      const level2Pool = [];
      const level2Group = {};
      let pool = [];
      const newColumns = [];
      this.headerGroup.forEach(el => {
        if (el.children && el.children.length > 0) {
          if (
            !Tsrv.utils.find(el.children, item => !isNaN(Number(item.field)))
          ) {
            level2Pool.push(el);
            pool = pool.concat(el.children.map(item => item.field));
          } else {
            level3Pool.push(el);
            pool = pool.concat(el.children.map(item => item.field));
          }
        }
      });
      level2Pool.forEach(el => {
        level2Group[el.title] = [];
        el.children.forEach(item => {
          const find = Tsrv.utils.find(columns, item2 =>
            ifFind(item2.field, item.field)
          );
          if (find) {
            level2Group[el.title].push(find);
          }
        });
      });

      level3Pool.forEach(el => {
        level3Group[el.title] = [];
        el.children.forEach(item => {
          if (!isNaN(Number(item.field))) {
            const title = this.headerGroup[Number(item.field) - 1].title;
            if (level2Group[title]) {
              level3Group[el.title].push({
                title,
                children: level2Group[title]
              });
              delete level2Group[title];
            }
          } else {
            const find = Tsrv.utils.find(columns, item2 =>
              ifFind(item2.field, item.field)
            );
            if (find) {
              level3Group[el.title].push(find);
            }
          }
        });
      });

      columns.forEach(el => {
        if (Tsrv.utils.find(pool, item => ifFind(el.field, item))) {
          let find = null;
          for (const key in level3Group) {
            if (level3Group[key][0].children) {
              if (ifFind(level3Group[key][0].children[0].field, el.field)) {
                find = {
                  title: key,
                  children: level3Group[key]
                };
                break;
              }
            } else {
              if (ifFind(level3Group[key][0].field, el.field)) {
                find = {
                  title: key,
                  children: level3Group[key]
                };
                break;
              }
            }
          }
          if (find === null) {
            for (const key in level2Group) {
              if (ifFind(level2Group[key][0].field, el.field)) {
                find = {
                  title: key,
                  children: level2Group[key]
                };
                break;
              }
            }
          }
          if (find !== null) {
            newColumns.push(find);
          }
        } else {
          newColumns.push(el);
        }
      });
      return newColumns;
    }
    return columns;
  }

  public setPidSetting(key, value) {
    this.pidSetting[key] = value;
  }

  // 转化layout的column为vxetable的column
  private transformColumns(columns: any) {
    this.isShowFooter = false;
    this.footerData = {};
    let vxeColumns = [];
    columns.forEach((el: any) => {
      this.footerData[el.field] = '';

      vxeColumns.push(this.getClmsWithConfig(el));
    });
    this.storedColumns = Tsrv.utils.clone(vxeColumns, true);

    vxeColumns = this.setColumnsGroup(vxeColumns);

    vxeColumns.unshift({
      field: 'id',
      title: 'ID',
      width: '50',
      align: 'center',
      visible: false,
      editRender: {
        name: 'oIdRender'
      }
    });

    vxeColumns.unshift({
      type: 'seq',
      width: '50',
      align: 'center',
      fixed: vxeColumns.find(ele => {
        return !Tsrv.utils.noValue(ele?.fixed) && ele.fixed === 'left';
      })
        ? 'left'
        : ''
    });

    if (this.getMultipleSelection()) {
      vxeColumns.unshift({
        type: 'checkbox',
        width: '50',
        align: 'center',
        visible: true,
        fixed: 'left'
      });
    }
    return vxeColumns;
  }

  private getMultipleSelection(): boolean {
    // this._config.multipleSelection 优先
    if (typeof this._config?.multipleSelection === 'boolean') {
      return this._config.multipleSelection;
    }
    return this.multipleSelection;
  }

  // 列json转为vxetable的配置
  private getClmsWithConfig(e: any) {
    // 设置字段名称、翻译、可排序
    const column: N_grid.TableColumn = {};
    column.params = {};
    column.params.source = e;
    column.params.filters = [];
    column.params.filtersSelected = [];
    column.params.isI18n = false;
    // 字段过滤下拉的数据 请求参数
    column.params.filterListParams = {
      currentPage: 1,
      pageSize: 30,
      total: 0,
      searchKey: ''
    };
    // const funI18nFields = this._config.funI18nFields ?? [];
    const funI18nFields = this.funI18nFields ?? [];
    funI18nFields.forEach(i18nField => {
      if (i18nField.indexOf('|') > 0 && i18nField.split('|')[1] === e.field) {
        column.params.isI18n = true;
      } else if (i18nField === e.field) {
        column.params.isI18n = true;
      }
    });

    // 渲染器
    column.editRender = {
      name: '',
      props: {
        size: 'small',
        disabled: !!e.disabled,
        placeholder: e.placeholder ?? '',
        funName: this.GT_editor.getFunName()
      },
      autoselect: true,
      events: {},
      attrs: {}
    };

    let field = e.field; // 原始字段
    let isM2o = false;
    let isSelection = false;
    let isAuxProp = false;

    // 配置m20/下拉/子查询
    if (
      e.many2one &&
      e.many2one !== '' &&
      e.many2one.toTable !== '' &&
      e.many2one.toTable !== null
    ) {
      const m2o = Tsrv.utils.getM2OConfig(e.many2one);
      column.editRender.props['m2oConfig'] = m2o;
      column.editRender.props['isDropdown'] = !!m2o.isDropdown;
      isM2o = true;
      let flag = true;
      for (let i = 0; i < m2o.fields.length; i++) {
        if (m2o.fields[i].isReturn === true) {
          flag = false;
          break;
        }
      }
      let isWarn = false;
      if (flag) {
        if (!m2o.toField) {
          isWarn = true;
          console.warn(
            `在配置多对一字段时发现空值，可能会影响显示数据:toTable:${m2o.toTable},toField=null`
          );
        }
        if (!m2o.toTable) {
          isWarn = true;
          console.warn(
            `在配置多对一字段时发现空值，可能会影响显示数据:toTable=null,toField=${m2o.toField}`
          );
        }
        if (!e.field) {
          isWarn = true;
          console.warn(
            `在配置多对一字段时发现空值，可能会影响显示数据:toTable:${m2o.toTable},toField:${m2o.toField}`
          );
        }
        if (isWarn) {
          field = e.field;
        } else {
          field = `m2o|${e.field}|${m2o.toTable}|${m2o.toField}`;
        }
        // 将所有m2o字段添加到
        this.GT_editor.setM2oList({
          field: e.field, // 原始字段
          tTable: m2o.toTable, // 目标表
          tField: m2o.toField, // 目标字段
          m2oField: field // 目标值
        });
        this.validRules[field] = this.validRules[e.field];
      }
    } else if (e.selectionID && e.selectionID !== null) {
      const slcField = `slc|${e.field}|${e.selectionID}`;
      isSelection = true;
      this.GT_editor.setSlcList({
        field: e.field, // 原始字段
        slcField // 目标值
      });
      this.validRules[slcField] = this.validRules[e.field];
    } else if (!Tsrv.utils.isEmpty(e.subQuery)) {
      this.subQueryArr.push(field);
    } else if (e.auxProp && e.auxProp !== '') {
      isAuxProp = true;
    }

    // 字段名
    column.field = field;
    column.title = !Tsrv.utils.isEmpty(e.comment) ? e.comment : e.field;

    // 筛选和排序
    column.sortable = true;

    // 筛选工具
    column.filters = [{ data: null }];
    column.filterRender = {
      name: 'oFilterInput'
      // name: 'FilterContent'
    };
    column.headerAlign = 'center';

    column.params.loadFilterList = this.loadFilterList;
    column.params['getTcommand'] = () => this.GT_editor;

    // 字段前缀
    if (e?.fieldPrefix) {
      const prefix = e.fieldPrefix;
      if (!Tsrv.noValue(prefix?.content)) {
        column.titlePrefix = {
          icon: prefix?.icon ? `wy-icon ${prefix.icon}` : '',
          iconStatus: prefix?.iconStatus ?? '',
          content: prefix?.content ?? ''
        };
      }
    }

    // 字段后缀
    if (e?.fieldSuffix) {
      const suffix = e.fieldSuffix;
      if (!Tsrv.noValue(suffix?.content)) {
        column.titleSuffix = {
          icon: suffix?.icon ? `wy-icon ${suffix.icon}` : '',
          iconStatus: suffix?.iconStatus ?? '',
          content: suffix?.content ?? ''
        };
      }
    }

    // 是否隐藏
    if (e.isShow === false) {
      column.visible = false;
    }

    if (e.fixedLeft === true && e.fixedRight !== true) {
      column['fixed'] = 'left';
    }

    if (e.fixedRight === true && e.fixedLeft !== true) {
      column['fixed'] = 'right';
    }

    if (e.disabled === true) {
      column['params'].disabled = true;
    }

    if (e.defaultFilter) {
      column.params.isDefaultFilter = true;
    }

    // 最小宽度
    if (e.minWidth && e.minWidth !== '') {
      column.minWidth = e.minWidth;
    } else {
      column.minWidth = '70px';
    }
    // 初始过滤
    if (e.initFilter && e.initFilter !== '') {
      // 如果初始过滤字段是m2o字段
      if (typeof field === 'string' && field.includes('m2o|')) {
        const initField: string = field.split('|')[1];
        this.GT_editor.addInitFilter(initField, e.initFilter);
      } else {
        this.GT_editor.addInitFilter(field, e.initFilter);
      }
      this.pidSetting[field] = e.initFilter;
    }

    // 默认过滤
    if (e.filter !== undefined && e.filter !== '') {
      this.pendingFilter.push({
        field,
        value: e.filter
      });
    }

    // 初始排序
    if (e.initSort && e.initSort !== '') {
      this.GT_editor.addSort(
        field,
        e.initSort,
        Tsrv.utils.toNumber(e.initSortWeight)
      );
    }

    // 对齐
    column.align = e.align || 'left';

    // 汇总
    if (Tsrv.utils.isNumber(e.footerMethod)) {
      column.params.footerMethod = e.footerMethod;
      this.tableStyle.showFooter && (this.isShowFooter = true);
    }
    if (e.type) {
      // 获取数据类型和长度
      let length = e.type.match(/\(([^)]*)\)/);
      let type = e.type.toLowerCase();
      const formatType = Tsrv.utils.get(e.formatter, 'type');
      if (length != null) {
        type = type.replace(/\(.*?\)/, '');
        length = length[1];
      }

      type = vxeConfig.grid.getRenderType(type, formatType, {
        isM2o,
        isSelection,
        isAuxProp
      });
      if (type === 'file') column.minWidth = '120px';
      vxeConfig.grid.getRender(
        this.mainFunName,
        column,
        type,
        formatType,
        this.GT_editor.getDbType(),
        this.$i18n.locale || 'en-US',
        {
          formatter: e.formatter,
          selectionID: e.selectionID,
          auxProp: e.auxProp,
          actions: e.actions,
          imgHeight: e.imgHeight,
          events: {
            'on-focus': this.listenFieldEvent,
            'on-blur': this.listenFieldEvent,
            'on-mouseleave': this.listenFieldEvent,
            'on-mouseenter': this.listenFieldEvent,
            'on-enter': this.listenFieldEvent,
            'on-dochange': this.listenFieldEvent
            // 'on-dochange': this.listenDoChange
          }
        },
        this.GT_editor
      );
    }
    // 操作列配置数据 （后续若在配置中添加该项配置信息，可在此修改逻辑）
    this.operateColumnConfig.usable.add(e.field);
    this.operateColumnConfig.display.add(e.field);
    return column;
  }

  private listenFieldEvent(e: any, type: string) {
    this.updateSaveBtnStatus();
    let actions = [];
    if (this.isIndependent) {
      if (e.column.editRender.attrs['actions']) {
        actions = e.column.editRender.attrs['actions'];
      }
      if (!Tsrv.utils.noValue(type) && !Tsrv.utils.noValue(actions)) {
        const action = Tsrv.utils.find(
          actions,
          item => item.eventType === type
        );
        if (!Tsrv.utils.noValue(action) && !Tsrv.utils.noValue(action.pubApi)) {
          const field = e?.column?.property;
          // if (field.indexOf('|') && !Tsrv.noValue(field.split('|')[1])) {
          //   field = field.split('|')[1];
          // }
          const params = this.GT_editor.getSelectedData('current');
          params.title = field;
          params['field'] = field;
          params.from = 'fieldEvent';
          this.GT_editor.doEvent(action.pubApi, params, { fieldData: e });
        }
      }
    } else {
      this.$emit('on-change', {
        index: this.parentID,
        data: e,
        eventType: type,
        funName: this.GT_editor.getFunName(),
        tableName: this.GT_editor.getTableName(),
        comp: this,
        fromComponent: 'table'
      });
    }
  }

  private onFieldEvent(e: any, fieldInstance: object, type: string) {
    let actions = [];
    if (this.isIndependent) {
      actions = fieldInstance['actions'];
      if (!Tsrv.utils.noValue(type) && !Tsrv.utils.noValue(actions)) {
        const action = Tsrv.utils.find(
          actions,
          item => item.eventType === type
        );
        if (!Tsrv.utils.noValue(action) && !Tsrv.utils.noValue(action.pubApi)) {
          const params = this.GT_editor.getSelectedData('current');
          params.title = fieldInstance['field'];
          params['field'] = fieldInstance['field'];
          params.from = 'fieldEvent';
          this.GT_editor.doEvent(action.pubApi, params, { fieldData: e });
        }
      }
    }
    //  else {
    //   this.$emit('on-change', {
    //     index: this.parentID,
    //     data: e,
    //     eventType: type,
    //     funName: this.GT_editor.getFunName(),
    //     tableName: this.GT_editor.getTableName(),
    //     comp: this,
    //     fromComponent: 'table'
    //   });
    // }
  }

  public openFileManager(row) {
    // 文件管理考虑放在mongoDB微服务先注解???
    // Tsrv.utils.getFileInfoById(row._file_info_id_).then(value => {
    //   if (value) {
    //     this.openUploadFile(value, row);
    //   } else {
    //     // this.$msg("找不到附件信息");
    //     this.$msg(Tsrv.getI18nByPath('oBaseGrid.cannotfindinfo'));
    //   }
    // });
    this.$msg(Tsrv.getI18nByPath('oBaseGrid.cannotfindinfo'));
  }

  public loadFilterList(
    field: string,
    reqParams: { currentPage: number; pageSize: number; filter: any }
  ): Promise<any> {
    return this.GT_editor.loadFilterList(field, reqParams);
  }

  // /**
  //  * 单列排序
  //  */
  // public addSort(
  //   field: string,
  //   value: string | number | null = null,
  //   weight?: number
  // ) {
  //   const o = this.sort[field];
  //   if (o) {
  //     if (o.value === value || value === null) {
  //       delete this.sort[field];
  //     } else {
  //       this.sort[field] = {
  //         value,
  //         weight: weight !== undefined ? weight : this.sortArr.length
  //       };
  //     }
  //   } else {
  //     this.sort[field] = {
  //       value,
  //       weight: weight !== undefined ? weight : this.sortArr.length
  //     };
  //   }

  //   this.sortArr = [];
  //   for (const key in this.sort) {
  //     this.sortArr.push({
  //       field: key,
  //       value: this.sort[key].value,
  //       weight: this.sort[key].weight
  //     });
  //   }
  //   this.sortArr = Tsrv.utils.sortBy(this.sortArr, 'weight').reverse();
  // }

  /**
   * 排序方法
   */
  // 改变排序条件
  private sortChange(e: any) {
    this.GT_editor.sortChange(e);
    this.seqStartIndex = 0;
    this.tablePage.currentPage = 1;
    this.GT_editor.loadTableData();
  }

  // // 当前field，当前排序顺序是否激活
  // private isSortIconActived(key: string, order: string) {
  //   const columnIndex = this.GT_editor.getGrid().getColumnIndex(
  //     this.GT_editor.getGrid().getColumnByField(key)
  //   );
  //   const ele = this.GT_editor.getGrid().$vnode.elm as HTMLElement;
  //   const sortColumnNode = ele.querySelector('.vxe-header--row')?.children[
  //     columnIndex
  //   ];
  //   const sortIcon = sortColumnNode?.querySelector(`.vxe-sort--${order}-btn`);
  //   return sortIcon?.classList.contains('sort-filter-active');
  // }

  /**
   * pageChange 翻页
   */
  private pageChange(e: any) {
    if (
      this.tablePage.currentPage !== e.currentPage ||
      this.tablePage.pageSize !== e.pageSize
    ) {
      this.tablePage.currentPage = e.currentPage;
      this.tablePage.pageSize = e.pageSize;
      if (this.dataSource === 'advq') {
        // 2.0版本此处需要评估
        this.GT_editor.loadTableDataAdvq();
      } else {
        this.GT_editor.loadTableData();
      }
    }
  }

  public removeSelected() {
    const params = {
      pTableName: this.GT_editor.getTableName(),
      pFunName: this.GT_editor.getFunName(),
      pIDs: this.GT_editor.getGrid()
        .getCheckboxRecords()
        .filter(el => {
          return !!el.id;
        })
        .map(el => el.id)
    };
    // 2.0通过规则处理单身删除前处理不可以写死 先注解
    // Tsrv.httpReqV1.fun('_sys_p_deleteRows_before', params).then(res => {
    //   if (res.data.success) {
    this.GT_editor.getGrid().remove(
      this.GT_editor.getGrid().getCheckboxRecords()
    );
    this.checkboxChange(null);
    this.updateSaveBtnStatus();
    this.editStatus = true;
    if (!this.isIndependent) {
      this.$emit('on-change', {
        index: this.parentID,
        data: null,
        eventType: 'dochange',
        funName: this.GT_editor.getFunName(),
        tableName: this.GT_editor.getTableName()
      });
    }
    //   }
    // });
  }

  // 命令执行
  public commitEvent(val: string, params: any = null) {
    switch (val) {
      // 第一行插入并激活
      case 'insert_actived':
        // 插入数据
        // if (this._config.insertMethod === 'card') {
        if (Tsrv.getx(this._config, 'triggerEvent.rowDbClick', false)) {
          this.showRowEditor(); // 打开行编辑器
        } else {
          this.GT_editor.sendEventCoordination('insert');
          this.GT_editor.editorStatus = 'new';
          this.editStatus = true;
          this.isEditable = true;
          this.insertRow(-1);
        }
        break;
      // 临时移除
      case 'remove':
        this.remove();

        break;
      // 直接删除
      case 'delete':
        this.GT_editor.sendEventCoordination('delete');
        this.delete();
        break;
      // 保存
      case 'save':
        // this.GT_editor.editorStatus = 'none';
        // this.GT_editor.save();
        // this.GT_editor.callControlEvent('refresh');
        this.saveVerification();
        break;
      // 打开导入
      case 'open_import':
        this.import();
        // this.GT_editor.getGrid().openImport({});
        break;
      // 打开导出
      case 'open_export':
        this.GT_editor.getGrid().openExport({});
        break;
      // 导出xml
      case 'export_xml':
        this.GT_editor.exportXml();
        break;
      // 重载
      case 'reload':
        this.GT_editor.handleBtnActions('refresh', this.reload);
        break;
      // 清除所有条件并载入数据
      case 'clearFilters':
        this.GT_editor.editorStatus = 'none';
        this.GT_editor.clearFiltersAndLoadData();
        break;

      // 刷新\清除条件
      case 'refresh':
        this.GT_editor.sendEventCoordination('refresh');
        this.GT_editor.editorStatus = 'none';
        // this.storedSelection = [];
        this.GT_editor.loadTableData();
        this.GT_editor.unLockALL(); // 解锁
        this.GT_editor.getCustBtnStatus(); // 刷新记忆自定义按钮状态
        break;
      // 直接写值？先注解
      // case 'importErrorFilter':
      //   if (params) this.addFilter('FStatus', '3cbec5745f51eacf');
      //   else this.addFilter('FStatus', '');
      //   this.GT_editor.loadTableData();
      //   break;
      case 'customBtnAction':
        this.GT_editor.doCustomBtnAction(params.title, params.action);
        break;
      case 'print':
        this.GT_editor.print();
        break;
      case 'edit':
        this.GT_editor.btnEdit(params);
        this.editStatus = params;
        break;
      case 'check':
        this.auditCheck('check', params);
        break;
      case 'queryLink':
        this.queryLinkClick(params);
        break;
      case 'selbill':
        this.selbillClick(params);
        break;
      case 'showSearch':
        this.showSearch();
        break;
      case 'setGraphVisible':
        this.setGraphVisible(params);
        break;
      case 'filter':
        this.filterClick();
        break;
      case 'tableQuery':
        this.tableQueryClick();
        break;
      case 'bancodeScan':
        this.bancodeScanClick();
        break;
      case 'requestAudit':
        this.requestAudit(params);
        break;
      case 'auditStatus':
        this.auditStatus();
        break;
      case 'accountPost':
        this.accountPost(params);
        break;
      case 'caseclose':
        this.caseclose(params);
        break;
      case 'freeze':
        this.freeze(params);
        break;
      case 'void':
        this.void();
        break;
      default:
    }
  }

  requestAudit(value: boolean) {
    if (value) {
      // 送审
      const rows: any = this.GT_editor.getGrid()
        .getCheckboxRecords()
        .filter(el => {
          return !!el.id;
        });
      if (rows.length !== 0) {
        const rowsID = rows.map(el => {
          return el.id;
        });
        const funInfo = {
          funID: this.funID,
          funName: this.tableName
        };
        vxeConfig.doRequestAudit(funInfo, rowsID).then(resp => {
          if (resp) {
            const actionsCfg = this.GT_editor.getActionCfg();
            const befEvent = actionsCfg.beforeRequestAudit;
            const aftEvent = actionsCfg.afterRequestAudit;
            this.doAuditCheck('requestAudit', true, { befEvent, aftEvent })
              .then(([b, _, er]) => {
                if (b) {
                  this.GT_editor.loadTableData();
                } else {
                  this.$msg(er ?? er);
                }
              })
              .catch(e => {
                console.error(e);
              });
          }
        });
      }
    } else {
      // 反审核
      this.auditCheck('antiAudit', value);
    }
  }

  // 审核状态
  private auditStatus() {}

  // 过账·取消过账
  private accountPost(value: boolean) {
    this.auditCheck('accountPost', value);
  }

  // 结案·反结案
  private caseclose(value: boolean) {
    this.auditCheck('caseclose', value);
  }

  // 冻结·解冻
  private freeze(value: boolean) {
    this.auditCheck('freeze', value);
  }

  // 作废
  private void() {
    this.auditCheck('void');
  }

  private async saveVerification() {
    const errMap = await this.grid.validate(true);
    if (errMap) {
      this.$Message.warning(Tsrv.getI18nByValue('校验不通过！') as string);
    } else {
      this.GT_editor.save();
      this.GT_editor.callControlEvent('refresh');
    }
  }

  private filterClick() {
    if (this.filterToolbarStatus) {
      this.filterToolbarStatus = false;
      this.filterModalShow = -1;
      this.GT_editor.clearFilter();
      this.GT_editor.loadTableData();
    } else {
      this.filterModalShow = 1;
    }
  }

  // 外部调用
  public loadTableData() {
    this.GT_editor.loadTableData();
  }

  public setGraphVisible(data: any, config?: any) {
    return new Promise(resolve => {
      for (const key in this.charts) {
        const flag = !!Tsrv.utils.find(data, el => el === key);
        this.charts[key].forEach((graph: any) => {
          graph.isShow = flag;
        });
        const find = Tsrv.utils.find(this.graphGroup, el => el.name === key);
        if (find) {
          find.value = flag;
        }
      }
      const find = Tsrv.utils.find(this.graphGroup, el => el.name === 'table');
      find.value = data.indexOf('table') > -1;
      return this.setCharts(config || this._config.charts, true);
    });
  }

  /**
   * @description: 初始化 详查（扫码） 位置
   * @return {*}
   * @author: swc
   * @Date: 2024-05-25 18:16:39
   * @LastEditors: swc
   * @LastEditTime: Do not edit
   */
  private initExtraPart() {
    const qbeSearch = this._config?.qbeSearch;
    if (!Tsrv.noValue(qbeSearch)) {
      if (qbeSearch?.enable && qbeSearch?.isInitShow) {
        this.tableQueryClick();
      }
    }
  }

  // 条码扫描
  private bancodeScanClick() {
    this.setGridHeadPosition('bancodeScan');
    // 打开 条码扫描
    this.gridHead.bancodeScan = !this.gridHead.bancodeScan;
    const position = Tsrv.utils.clone(
      Tsrv.getx(this._config, 'bancodeScan.position', 'top'),
      true
    );
    let initSpace =
      Tsrv.utils.clone(
        Tsrv.getx(this._config, 'bancodeScan.initSpace', 5),
        true
      ) / 100;
    if (initSpace < 0.05) {
      initSpace = 0.05;
    }
    if (this.gridHead.bancodeScan) {
      // this.gridHead.qbeQuery = false;
      Object.keys(this.gridHead).forEach(key => {
        if (key !== 'bancodeScan') {
          this.gridHead[key] = false;
        }
      });
      this.collapseStyle['--splitTrigger'] = undefined;
      position === 'top'
        ? (this.searchControl.split = initSpace)
        : position === 'bottom'
        ? (this.searchControl.split = 1 - initSpace)
        : position === 'left'
        ? (this.searchControl.split = initSpace)
        : (this.searchControl.split = 1 - initSpace);
    } else {
      this.collapseStyle['--splitTrigger'] = 'none';
      position === 'top'
        ? (this.searchControl.split = 0)
        : position === 'bottom'
        ? (this.searchControl.split = 1)
        : position === 'left'
        ? (this.searchControl.split = 0)
        : (this.searchControl.split = 1);
    }
  }

  // QBE 的form实例注册到指挥部
  private regCompItem(compBoxInfo: ifs.I_compBoxInfo, key: string) {
    this.GT_editor.regCompItem(compBoxInfo, key);
  }

  private tableQueryClick() {
    this.setGridHeadPosition('qbeSearch');
    // 打开QBE 搜索
    this.gridHead.qbeSearch = !this.gridHead.qbeSearch;
    const position = Tsrv.utils.clone(
      Tsrv.getx(this._config, 'qbeSearch.position', 'top'),
      true
    );
    let initSpace =
      Tsrv.utils.clone(
        Tsrv.getx(this._config, 'qbeSearch.initSpace', 5),
        true
      ) / 100;
    if (initSpace < 0.05) {
      initSpace = 0.05;
    }
    if (this.gridHead.qbeSearch) {
      this.gridHead.bancodeScan = false;
      // Object.keys(this.gridHead).forEach(key => {
      //   if (key !== 'qbeSearch') {
      //     this.gridHead[key] = false;
      //   }
      // })
      this.collapseStyle['--splitTrigger'] = undefined;
      position === 'top'
        ? (this.searchControl.split = initSpace)
        : position === 'bottom'
        ? (this.searchControl.split = 1 - initSpace)
        : position === 'left'
        ? (this.searchControl.split = initSpace)
        : (this.searchControl.split = 1 - initSpace);
    } else {
      this.collapseStyle['--splitTrigger'] = 'none';
      position === 'top'
        ? (this.searchControl.split = 0)
        : position === 'bottom'
        ? (this.searchControl.split = 1)
        : position === 'left'
        ? (this.searchControl.split = 0)
        : (this.searchControl.split = 1);
      // 关闭qbe查询，qbe过滤条件清空并刷新数据
      this.GT_editor.getCompItemByName('queryByExample').setFormData();
      this.doSimpleSearch();
    }
    this.$nextTick(() => {
      this.GT_editor.getCompItemByName('queryByExample').setColumns(
        this.queryItems()
      );
      this.GT_editor.getCompItemByName('queryByExample').setColumnNumber(
        null,
        true
      );
    });
  }

  public queryItems(): any {
    const items = [];
    const grid = Tsrv.utils.clone(this.grid.columns, true);
    grid.forEach(el => {
      if (el.editRender && el.field !== 'id' && !!el.params.isDefaultFilter) {
        el.itemRender = vxeConfig.getSearchRender(el.editRender);
        // delete el.editRender;
        // 统一换成oSearch组件
        el.itemRender.originName = el.itemRender.name;
        el.itemRender.name = 'oSearch';
        if (el.field.indexOf('m2o|') > -1) {
          el.field = el.field.split('|')[1];
        }
        el.itemRender.props['type'] = el.params.source.type;
        el.itemRender.props['column'] = this.grid.getColumnByField(el.field);
        el['params']['table'] = el.itemRender.name;
        if (Tsrv.utils.noValue(el?.visible) || el.visible) {
          items.push(el);
        }
      }
    });
    items.push({
      align: 'center',
      span: 2,
      itemRender: {
        name: '$button',
        props: {
          type: 'submit',
          // content: "搜索",
          content: Tsrv.getI18nByPath('oReportEditor.search'),
          status: 'primary'
        }
      }
    });
    return items;
  }

  // 执行QBE搜索
  public doSimpleSearch() {
    const arr = this.GT_editor.getCompItemByName(
      'queryByExample'
    ).getFilterData({
      hasM2o: true
    });
    this.isOpenSearch = false;
    this.GT_editor.clearFilter();
    arr.forEach(el => {
      this.GT_editor.addFilter(el.field, el.value);
    });
    this.GT_editor.loadTableData();
  }

  // 初始化QBE、扫码位置 split = >
  public setGridHeadPosition(type: string) {
    // enable position
    this.collapseStyle['--splitTrigger'] = 'none';
    // const position = this._config?.qbeSearch?.position ?? '';
    const position = Tsrv.utils.clone(
      Tsrv.getx(this._config, `${type}.position`, ''),
      true
    );
    if (!Tsrv.utils.noValue(position)) {
      if (position === 'top') {
        this.searchControl.split = 0;
        this.searchControl.modeStyle = 'vertical';
        this.searchControl.formPosition = 'top';
        this.searchControl.gridPosition = 'bottom';
      } else if (position === 'bottom') {
        this.searchControl.split = 1;
        this.searchControl.modeStyle = 'vertical';
        this.searchControl.formPosition = 'bottom';
        this.searchControl.gridPosition = 'top';
      } else if (position === 'left') {
        this.searchControl.split = 0;
        this.searchControl.modeStyle = 'horizontal';
        this.searchControl.formPosition = 'left';
        this.searchControl.gridPosition = 'right';
      } else if (position === 'right') {
        this.searchControl.split = 1;
        this.searchControl.modeStyle = 'horizontal';
        this.searchControl.formPosition = 'right';
        this.searchControl.gridPosition = 'left';
      }
    }
  }

  private doSearch() {
    const filters = this.$refs['searchForm'].getFilterData({
      hasM2o: true
    });
    this.isOpenSearch = false;
    this.GT_editor.clearFilter();
    filters.forEach(el => {
      this.GT_editor.addFilter(el.field, el.value);
    });

    this.GT_editor.loadTableData();
  }

  private resetSearchForm() {
    this.$refs['searchForm'].clearFormData();
  }

  private showSearch() {
    this.isOpenSearch = true;

    if (this.searchColumns.length === 0 && this.storedColumns) {
      const columns = Tsrv.utils.clone(this.storedColumns, true);
      columns.forEach(el => {
        if (
          el.editRender &&
          el.property !== 'id' &&
          el.editRender.name &&
          !!el.params.isDefaultFilter
        ) {
          if (el.editRender.name !== 'oFileInput') {
            el.itemRender = vxeConfig.getSearchRender(el.editRender);
            delete el.editRender;
            this.searchColumns.push(el);
          }
        }
      });
    }
    setTimeout(() => {
      if (this.$refs['searchForm']) {
        this.$refs['searchForm'].setColumns(this.searchColumns);
        this.$refs['searchForm'].setColumnNumber(1, true);
      }
    }, 0);
  }

  private selbillClick(index: number) {
    if (index !== null && !this.needSave) {
      const item = this._config.selbill[index];
      vxeConfig
        .selectBill(
          item,
          this.GT_editor.getTableName(),
          this.GT_editor.getFunName(),
          this.current.row
        )
        .then((res: any) => {
          if (res) {
            this.needSave = true;
            let data = res.rows[0].FRtlJson;
            data = Tsrv.utils.toStringJSON(data);
            if (data[this.GT_editor.getTableName()]) {
              data[this.GT_editor.getTableName()].forEach(el => {
                if (el.id) {
                  vxeConfig.grid.setRowDataById(
                    this.GT_editor.getGrid(),
                    el.id,
                    el
                  );
                } else {
                  this.insertRow(-1, { data: el });
                }
              });
            }
            this.updateSaveBtnStatus();
          } else {
            this.needSave = false;
          }
        })
        .catch(err => {
          throw new Error(err);
        });
    }
  }

  /**
   * 联查
   */
  private queryLinkClick(index: number, row: any = null) {
    if (index !== null) {
      const tableSelection = row || this.GT_editor.getGrid().getCurrentRecord();

      if (tableSelection) {
        const item = this._config.queryLink[index];

        const searchCfg = [];
        item.children.forEach(el => {
          if (tableSelection[el.field]) {
            searchCfg.push({
              field: el.toField,
              value: tableSelection[el.field]
            });
          }
        });
        this.addTabFunc(item.funName).then((res: any) => {
          setTimeout(() => {
            if (
              res.$children[0].$children[0] &&
              typeof res.$children[0].$children[0].requestFilter === 'function'
            ) {
              res.$children[0].$children[0].requestFilter(searchCfg);
            }
          }, 0);
        });
      }
    }
  }

  /**
   * 审核
   */
  // public auditCheck(value: boolean) {
  //   const title = value
  //     ? Tsrv.getI18nByPath('vxe.toolbar.audit')
  //     : Tsrv.getI18nByPath('vxe.toolbar.unaudit');
  //   const action = value ? '_sys_p_billAudit' : '_sys_p_billUnAudit';
  //   const selection = this.GT_editor.getGrid()
  //     .getCheckboxRecords()
  //     .map(el => {
  //       return el.id;
  //     });

  //   if (selection.length > 0) {
  //     const params = {
  //       pTableName: this.GT_editor.getTableName(),
  //       pFunName: this.GT_editor.getFunName(),
  //       title: value ? 'audit' : 'unaudit',
  //       pBillID: selection
  //     };
  //     this.$Modal.confirm({
  //       title: Tsrv.getI18nBySrv(title),
  //       content: `${Tsrv.getI18nByPath('prompt.isExecute')}${Tsrv.getI18nBySrv(
  //         title
  //       )}`,
  //       onOk: () => {
  //         const msg = this.$Message.loading({
  //           content: `${Tsrv.getI18nByPath(
  //             'prompt.execute'
  //           )}${Tsrv.getI18nBySrv(title)}...`,
  //           duration: 0
  //         });

  //         // 表格暂定为 不参加 审批流  （审核前后回调暂不添加————后有可能删除调 basegrid组件 “审核”功能）
  //         this.GT_editor.doEvent(action, params)
  //           .then(b => {
  //             // @ts-ignore
  //             msg();
  //             if (b) {
  //               this.toolbar.audit.value = !value;
  //               this.GT_editor.loadTableData();
  //             }
  //           })
  //           .catch(e => {
  //             // @ts-ignore
  //             msg();
  //             this.$msg(e);
  //             console.error(e);
  //           });
  //       }
  //     });
  //   }
  // }

  public auditCheck(
    type:
      | 'check'
      | 'accountPost'
      | 'caseclose'
      | 'freeze'
      | 'void'
      | 'requestAudit'
      | 'antiAudit',
    status: boolean = true
  ) {
    let befEvent: string | undefined;
    let aftEvent: string | undefined;
    const actionsCfg = this.GT_editor.getActionCfg();
    switch (type) {
      case 'check': // 审核
        befEvent = status ? actionsCfg.beforeAudit : actionsCfg.beforeUnaudit;
        aftEvent = status ? actionsCfg.afterAudit : actionsCfg.afterUnaudit;
        break;
      case 'accountPost':
        befEvent = status
          ? actionsCfg.beforeAccountPosted
          : actionsCfg.beforeCancelPost;
        aftEvent = status
          ? actionsCfg.afterAccountPosted
          : actionsCfg.afterCancelPost;
        break;
      case 'caseclose':
        befEvent = status
          ? actionsCfg.beforeCaseclosed
          : actionsCfg.beforeAnticlosing;
        aftEvent = status
          ? actionsCfg.afterCaseclosed
          : actionsCfg.afterAnticlosing;
        break;
      case 'freeze': // 冻结
        befEvent = status ? actionsCfg.beforeFreeze : actionsCfg.beforeUnfreeze;
        aftEvent = status ? actionsCfg.afterFreeze : actionsCfg.afterUnfreeze;
        break;
      case 'void': // 作废
        befEvent = actionsCfg.beforeVoid;
        aftEvent = actionsCfg.afterVoid;
        break;
      case 'antiAudit': // 反审核
        befEvent = actionsCfg.beforeAntiaudit;
        aftEvent = actionsCfg.afterAntiaudit;
        break;
      default:
        break;
    }
    this.doAuditCheck(type, status, { befEvent, aftEvent })
      .then(([b, _, er]) => {
        if (b) {
          // this.toolbar.audit.value = !value;
          this.GT_editor.loadTableData();
        } else {
          this.$msg(er ?? er);
        }
      })
      .catch(e => {
        console.error(e);
      });
  }

  public doAuditCheck(
    type:
      | 'check'
      | 'accountPost'
      | 'caseclose'
      | 'freeze'
      | 'void'
      | 'requestAudit'
      | 'antiAudit',
    operate: boolean | undefined = undefined,
    events: any
  ): Promise<[boolean, ifs.I_setDataRes, string]> {
    const { befEvent, aftEvent } = events;
    let eventName: string = '';
    const selectedRecords = this.GT_editor.getGrid().getCheckboxRecords();
    const upd = new ts.T_ctdUpdRec();
    const updDs: ts.T_ctdUpdData[] = [];
    const rule = new ts.T_rule();
    selectedRecords.forEach((record: any) => {
      const updD = new ts.T_ctdUpdData();
      updD.setFilter({ id: { $eq: record?.id ?? '-1' } });
      const updataRecords: ifs.I_fv[] = [];
      switch (type) {
        case 'check': // 审核
          updataRecords.push(
            ...[
              { field: '_audited_', value: operate ? 1 : 0 } as ifs.I_fv,
              { field: '_status_', value: operate ? 101 : 0 } as ifs.I_fv
            ]
          );
          eventName = operate ? 'audit' : 'unaudit';
          break;
        case 'accountPost':
          updataRecords.push({
            field: '_status_',
            value: operate ? 200 : record['_previous_status_']
          } as ifs.I_fv);
          eventName = operate ? 'accountPost' : 'cancelPost';
          break;
        case 'caseclose':
          updataRecords.push({
            field: '_status_',
            value: operate ? 300 : record['_previous_status_']
          } as ifs.I_fv);
          eventName = operate ? 'caseclose' : 'anticlosing';
          break;
        case 'freeze': // 冻结
          updataRecords.push({
            field: '_status_',
            value: operate ? 999 : record['_previous_status_']
          } as ifs.I_fv);
          eventName = operate ? 'freeze' : 'unfreeze';
          break;
        case 'void': // 作废
          updataRecords.push({
            field: '_status_',
            value: -1
          } as ifs.I_fv);
          eventName = 'void';
          break;
        case 'antiAudit': // 反审核
          updataRecords.push(
            ...[
              { field: '_audited_', value: 0 } as ifs.I_fv,
              { field: '_status_', value: 100 } as ifs.I_fv
            ]
          );
          eventName = 'antiAudit';
          break;
        case 'requestAudit': // 送审
          updataRecords.push(
            ...[
              { field: '_audited_', value: 0 } as ifs.I_fv,
              { field: '_status_', value: 100 } as ifs.I_fv
            ]
          );
          // eventName = 'requestAudit';
          break;
        default:
          break;
      }
      updD.setRowData(...updataRecords);
      updDs.push(updD);
    });

    upd.setCtdUpdDatas(...updDs);

    const p = this.GT_editor.getSelectedData();

    if (befEvent) {
      const syncParams = new ts.T_syncParams();
      const _p = Tsrv.utils.clone(p, true);
      _p.from = `before${eventName}`;
      syncParams
        .setApiName(befEvent)
        .setUserInfo(Tsrv.getUserInfo() as ifs.I_userInfo)
        .setFunInfo(Tsrv.getFunInfo(this.funName) as ifs.I_funInfo)
        .setSyncData(_p);
      upd.setBefEvent(syncParams);
    }
    if (aftEvent) {
      const syncParams = new ts.T_syncParams();
      const _p = Tsrv.utils.clone(p, true);
      _p.from = `after${eventName}`;
      syncParams
        .setApiName(aftEvent)
        .setUserInfo(Tsrv.getUserInfo() as ifs.I_userInfo)
        .setFunInfo(Tsrv.getFunInfo(this.funName) as ifs.I_funInfo)
        .setSyncData(_p);
      upd.setAftEvent(syncParams);
    }

    return Tsrv.updRows(this.funName, this.GT_editor.getDbType(), rule, upd);
  }

  /**
   * 右键菜单点击事件
   */
  private handleContextMenuClick(e: any) {
    // 清空存放右键菜单实例的数据、删除右键菜单事件监听
    if (!Tsrv.noValue(this.contextMenuEl)) {
      this.contextMenuEl.removeEventListener(
        'mouseleave',
        this.menuMouseleaveListenCallback
      );
      this.contextMenuEl = null;
    }
    const row = e.row;
    // const rowIndex = e.rowIndex;
    const column = e.column;
    const menu = e.menu;
    if (menu.code.indexOf('|') > -1) {
      menu.action = menu.code.split('|')[1];
      menu.code = 'customBtnAction';
    }
    switch (menu.code) {
      // 标记删除
      case 'insertAbove':
        this.insertRow(row);
        break;
      case 'insertBelow':
        if (
          this.GT_editor.getGrid().getTableData().visibleData[
            this.current.rowIndex + 1
          ]
        ) {
          this.insertRow(
            this.GT_editor.getGrid().getTableData().visibleData[
              this.current.rowIndex + 1
            ]
          );
        } else {
          this.insertRow(-1);
        }
        break;
      case 'insertTop':
        this.insertRow(null);
        break;
      case 'insertBottom':
        this.insertRow(-1);
        break;
      case 'remove':
        if (row) {
          this.GT_editor.getGrid().setCheckboxRow(row, true);
          this.toolbar.delete.isDisable = false;
          this.commitEvent('remove');
        }
        break;
      // 直接删除
      case 'directRemove':
        if (row) {
          this.GT_editor.getGrid().setCheckboxRow(row, true);
          this.toolbar.delete.isDisable = false;
          this.commitEvent('delete');
        }
        break;
      // 清空单元格
      case 'clearCeil':
        if (row && column) {
          row[column.property] = vxeConfig.grid.getColumnDefaultVal(column);
        }
        break;
      // 清空行
      case 'clearRow':
        if (row) {
          for (const key in row) {
            if (key) {
              const property = this.GT_editor.getGrid().getColumnByField(key);
              if (property) {
                row[key] = vxeConfig.grid.getColumnDefaultVal(property);
              }
            }
          }
        }
        break;
      // 复制单元格
      case 'copyCeil':
        if (row && column) {
          const val = row[column.property];
          if (Clipboard.copy(val)) {
            this.$store.dispatch('setClipboard', val);
            this.$Message.success(Tsrv.getI18nByPath('prompt.copyToClipboard'));
          }
        }
        break;
      // 复制行
      case 'copyRow':
        if (row) {
          const rowData = Tsrv.utils.clone(row, true);
          delete rowData._XID;
          const val = JSON.stringify(rowData);
          if (val) {
            if (Clipboard.copy(val)) {
              this.$store.dispatch('setClipboard', val);
              this.$Message.success(
                Tsrv.getI18nByPath('prompt.copyToClipboard')
              );
            }
          }
        }
        break;
      case 'copyInsert':
        if (row) {
          const val = Tsrv.utils.clone(row, true);
          val.id = Tsrv.getSnowIDFmtStr();
          delete val._XID;
          if (val) {
            this.insertRow(-1, { data: val });
          }
        }
        break;
      // 粘贴单元格
      // case "pasteCeil":
      //   if (row && column) {
      //     const val = this.$store.getters.Clipboard;
      //     row[column.property] = val;
      //   }
      //   break;
      // 粘贴行
      case 'pasteRow':
        if (row) {
          const val = Tsrv.utils.toStringJSON(this.$store.getters.Clipboard);
          if (val) {
            Object.keys(val).forEach(key => {
              if (row[key] !== undefined) {
                row[key] = val[key];
              }
            });
          }
        }
        break;
      case 'setup':
        if (row) {
          const cf = {
            config: null,
            lockInfo: {
              row,
              funID: this.GT_editor.getFunID()
            }
          };
          if (row.fun_config) {
            const config = JSON.parse(row.fun_config);
            // Tsrv.utils.createModal('o-setup-panel', config);
            cf.config = config;
            Tsrv.utils
              .createModal('o-setup-panel', cf)
              .then(resp => {
                this.GT_editor.loadTableData();
              })
              .catch(err => {
                console.error(err);
              });
          } else {
            this.localData.forEach(el => {
              if (el.title === row.parent_fun_name) {
                const config = JSON.parse(el.fun_config);
                // 传row 方便加锁
                // Tsrv.utils.createModal('o-setup-panel', config);
                cf.config = config;
                Tsrv.utils
                  .createModal('o-setup-panel', cf)
                  .then(resp => {
                    this.GT_editor.loadTableData();
                  })
                  .catch(err => {
                    console.error(err);
                  });
              }
            });
          }
        }
        break;
      case 'customBtnAction':
        this.GT_editor.doCustomBtnAction(menu.name, menu.action);
        break;
      case 'attach':
        if (row) {
          let value = {
            fileList: []
          };
          if (row._file_) {
            value = Tsrv.utils.toStringJSON(row._file_) || {
              fileList: []
            };
            this.openUploadFile(value, row);
          } else if (row._file_info_id_) {
            // 文件管理考虑放在mongoDB微服务先注解???
            // Tsrv.utils.getFileInfoById(row._file_info_id_).then(v => {
            //   if (v) {
            //     this.openUploadFile(v, row);
            //   } else {
            //     this.$msg(Tsrv.getI18nByPath('warm.noFileInfo'));
            //   }
            // });
            this.$msg(Tsrv.getI18nByPath('warm.noFileInfo'));
          } else {
            this.openUploadFile(value, row);
          }
        }
        break;
      case 'modify':
        if (this._config.hasModifyBox) {
          Tsrv.utils
            .createModal('o-modify-box', {
              funName: this.GT_editor.getFunName(),
              config: Tsrv.utils.clone(this._config, true),
              data: Tsrv.utils.clone(row)
            })
            .then(data => {
              if (data) {
                data.forEach(el => {
                  if (el.field !== 'id') {
                    row[el.field] = el.value;
                  }
                });
                this.updateSaveBtnStatus();
              }
            });
        }
        break;

      case 'copyColunm':
        this.copyColunm.fromField = column.title;
        break;

      case 'pasteColunm':
        this.doPasteColunm(column.title);
        break;

      default:
        this.$Message.info({
          content: `${Tsrv.getI18nByPath('prompt.click')} "${menu.name}"`
        });
    }
  }

  /**
   * 获取右键菜单
   */
  private getContext() {
    const headerMenus: MenuFirstOption[] = [];
    const bodyMenus: MenuFirstOption[] = [
      [
        vxeConfig.grid.getInsertContext(this.toolbar, this.isEditable),
        vxeConfig.grid.getCopyContext(this.toolbar, this.isEditable),
        vxeConfig.grid.getPastContext(this.toolbar, this.isEditable),
        vxeConfig.grid.getClearContext(this.toolbar, this.isEditable),
        vxeConfig.grid.getRemoveContext(this.toolbar, this.isEditable)
      ]
      // [vxeConfig.grid.getAttachContext(this.toolbar, this.isEditable)]
    ];
    const footerMenus: MenuFirstOption[] = [];
    if (this.GT_editor.getTableName() === '_sys_fun') {
      bodyMenus.push([
        vxeConfig.grid.getSetupContext(this.toolbar, this.isEditable)
      ]);
    }
    if (this.toolbar?.addon) {
      const menus = [];
      this.toolbar.addon.forEach(el => {
        const menu = {
          code: `c|${el.action}`,
          name: el.title,
          prefixIcon: `wy-icon ${el.icon}`,
          visible: el.auth,
          disabled: false
        };
        if (el.children.length > 0) {
          menu['children'] = [];
          menu['children'].push(Tsrv.utils.clone(menu, true));
          el.children.forEach(child => {
            menu['children'].push({
              code: `c|${child.action}`,
              name: child.title,
              prefixIcon: child.icon,
              visible: el.auth,
              disabled: false
            });
          });
        }
        menus.push(menu);
      });
      bodyMenus.push(menus);
    }
    this._config?.hasModifyBox &&
      bodyMenus.push([
        vxeConfig.grid.getModifyContext(this.toolbar, this._config.hasModifyBox)
      ]);
    return {
      header: { options: headerMenus },
      body: { options: bodyMenus },
      footer: { options: footerMenus }
    };
  }

  private doPrint() {
    this.GT_editor.doPrint();
  }

  /**
   * globalSearch 全表模糊搜索
   */
  public globalSearch(text: string) {
    this.GT_editor.setGlobalSearchText(text);
    this.GT_editor.asnycGlobalSeachText(text);
    this.seqStartIndex = 0;
    this.tablePage.currentPage = 1;
    this.GT_editor.loadTableData();
  }

  private globalSeachValChange(text: string) {
    this.GT_editor.asnycGlobalSeachText(text);
  }

  private switchSearchMode() {
    this.isLexicon = !this.isLexicon;
  }

  /**
   * 发送数据到接受者
   */
  public sendSelection(msg: any) {
    const receiver = msg.receiver;
    const limit = msg?.limit || 1;
    const records = Tsrv.utils.clone(this.storedSelection, true);
    this.GT_editor.checkJsonField(records);
    const active = this.GT_editor.getGrid().getCurrentRecord();
    if (records) {
      if (active && records.length === 0) {
        records.push(active);
      }
      if (records.length <= limit) {
        this.sendBusEvent(
          'bus',
          receiver,
          records,
          this.GT_editor.getTableName()
        );
      }
    }
  }

  /**
   * （magicbox自定义按钮）发送数据到接受者
   */
  public custBtnRequestSend(msg: any) {
    const receiver = msg.receiver;
    const limit = msg?.limit || 1;
    const records = Tsrv.utils.clone(this.storedSelection, true);
    this.GT_editor.checkJsonField(records);
    const active = this.GT_editor.getGrid().getCurrentRecord();
    if (records) {
      if (active && records.length === 0) {
        records.push(active);
      }
      if (records.length <= limit) {
        this.sendBusEvent('bus', receiver, {
          _trigger_: {
            type: 'custBtn',
            data: msg?.button
          },
          data: records,
          tableName: this.GT_editor.getTableName()
        });
      }
    }
  }

  // 设置行默认数据
  public setAutoComplete(
    from: any,
    option?: {
      isAsFilter?: boolean;
      isReload?: boolean;
      isOverwrite?: boolean;
      isSetScope?: boolean;
    }
  ) {
    return new Promise(resolve => {
      // 如果表的筛选字段来自本身，常用语导航表来源于本表
      // 来源表
      const funName = this.GT_editor.getFunName();
      if (from.table === funName) {
        if (from.m2oField) {
          this.m2oSetting[from.m2oField] = from.data[from.m2oField];
          this.m2oSetting[from.field] = from.key;
        } else if (from.slcField) {
          this.slcSetting[from.slcField] = from.data[from.slcField];
          this.slcSetting[from.field] = from.key;
        }
        // 父ID
        if (from.pidField) {
          const pidfie = from.pidField;
          Object.keys(from.data).forEach(el => {
            // 如果pid字段是m2o字段
            if (el.indexOf(`m2o|${pidfie}`) > -1) {
              this.pidSetting[el] = from.data[el.split('|')[3]];
            }
          });
          // this.GT_editor.setM2oList(m2oPid);
          this.pidSetting[from.pidField] = from.key;
        }
      } else {
        const m2oList = this.GT_editor.getM2oList();
        for (const i in m2oList) {
          // 如果本表m2o信息的某toTable等于消息来源表的table，则进行设置
          if (
            m2oList[i].tTable === from.table ||
            m2oList[i].tTable === from.fromTable
          ) {
            // 设置转化后的字段信息（用于显示）
            if (from.data[m2oList[i].tField] !== undefined) {
              // 设置keyField用于导航
              this.keyField = m2oList[i].field;

              // 设置m2o字段信息
              this.m2oSetting[m2oList[i].m2oField] =
                from.data[m2oList[i].tField];
              this.m2oSetting[m2oList[i].field] = from.key;

              // 是否作为初始过滤
              if (option?.isAsFilter) {
                this.GT_editor.addInitFilter(m2oList[i].field, from.key);
              }

              // 是否立即重载
              if (option?.isReload) this.GT_editor.loadTableData();

              // 是否覆盖
              if (
                option?.isOverwrite === true &&
                from.data[m2oList[i].tField]
              ) {
                this.GT_editor.getGrid()
                  .getTableData()
                  .fullData.forEach(el => {
                    el[m2oList[i].field] = from.key;
                    el[m2oList[i].m2oField] = from.data[m2oList[i].tField];
                  });
              }
              // 是否设为更新范围
              option?.isSetScope &&
                this.GT_editor.setScope(m2oList[i].field, from.key);
              break;
            }
          }
        }
      }
      resolve(true);
    });
  }

  public setLinkParent(v: any) {
    this.linkParent = {
      defaultVal: v?.defaultVal ?? [], // 多字段插入默认值
      funName: this.GT_editor.getTableName(),
      rowID: v.data.id,
      mainFunName: v.table
    };
  }

  /**
   * insertRow 插入行
   * @param index 1、-1最后一行，2、null第一行，3、row行之上
   * @param options active? 是否激活
   */
  // 插入行
  public insertRow(index: any, options?: { active?: boolean; data?: any }) {
    const fields = this.GT_editor.getFields();
    let row: RowInfo = {};
    if (this._config.hasModifyBox) {
      let fillData = {};
      if (options?.data) {
        fillData = options.data;
      }
      fields.forEach(key => {
        if (this.m2oSetting[key] !== undefined) {
          row[key] = this.m2oSetting[key]; // 设置对应字段
          const realField: string = vxeConfig.grid.getRealField(key);
          row[realField] = this.m2oSetting[realField]; // 设置原字段
        }
        if (this.slcSetting[key] !== undefined) {
          row[key] = this.slcSetting[key]; // 设置对应字段
        }
        if (this.pidSetting[key] !== undefined) {
          row[key] = this.pidSetting[key];
        }
      });

      const TdevVal = new ts.T_defVal();
      TdevVal.setLang(this.$i18n.locale)
        .setDbType('mysql')
        .setFunName(this.GT_editor.getFunName());
      TdevVal.setMainfunName(this.linkParent.mainFunName).setRowID(
        this.linkParent.rowID
      );
      Tsrv.getDefaultVal(TdevVal)
        .then(r => {
          r.forEach(fv => {
            if (fields.has(fv.field)) {
              row[fv.field] = fv.value;
              Tsrv.utils
                .createModal('o-modify-box', {
                  funName: this.GT_editor.getFunName(),
                  config: Tsrv.utils.clone(this._config, true),
                  data: row
                })
                .then(data => {
                  if (data) {
                    this.GT_editor.getGrid()
                      .insertAt(null, index)
                      .then(rs => {
                        data.forEach(el => {
                          if (el.field !== 'id') {
                            rs.row[el.field] = el.value;
                          }
                        });
                        this.GT_editor.getGrid().scrollToRow(rs.row);
                        this.setCurrentRow(rs.row);
                        this.GT_editor.getGrid().setCurrentRow(rs.row);
                        // 排序
                        this.GT_editor.updateSortNum(index);
                        this.updateSaveBtnStatus();
                      });
                  }
                });
            }
          });
        })
        .catch(r => {
          throw new Error('getDefValErr:', r);
        });
    } else {
      let fillData = {};
      if (options?.data) {
        fillData = options.data;
        delete fillData['id'];
      }
      this.GT_editor.getGrid()
        .insertAt(null, index)
        .then(async res => {
          // 返回row
          row = res.row;
          Object.keys(row).forEach(k => {
            fields.add(k);
          });
          // m2o，slc，pid默认值插入
          fields.forEach(key => {
            if (this.m2oSetting[key] !== undefined) {
              row[key] = this.m2oSetting[key]; // 设置对应字段
              const realField: string = vxeConfig.grid.getRealField(key);
              row[realField] = this.m2oSetting[realField]; // 设置原字段
            }
            if (this.slcSetting[key] !== undefined) {
              row[key] = this.slcSetting[key]; // 设置对应字段
            }
            if (this.pidSetting[key] !== undefined) {
              row[key] = this.pidSetting[key];
            }
            // if (key === 'id') {
            //   row[key] = Tsrv.getSnowIDFmtStr();
            // }
            if (!Tsrv.utils.noValue(this.linkParent.defaultVal)) {
              for (const f of this.linkParent.defaultVal) {
                if (f.field === key) {
                  row[key] = f.value;
                  break;
                }
              }
            }
          });
          if (fields.has('id')) {
            row['id'] = await Tsrv.getSnowIDFmtStr();
          }

          this.GT_editor.getGrid().scrollToRow(row);
          for (const key in fillData) {
            row[key] = fillData[key];
          }
          this.setCurrentRow(row);
          this.GT_editor.getGrid().setCurrentRow(row);

          // 判断是否激活
          let activeFlag = true;
          if (options) {
            if (options.active === false) {
              activeFlag = false;
            }
          }
          if (activeFlag) {
            setTimeout(() => {
              this.setActiveRow(row);
            }, 0);
          }

          const TdevVal = new ts.T_defVal();
          TdevVal.setLang(this.$i18n.locale)
            .setDbType('mysql')
            .setFunName(this.GT_editor.getFunName());
          TdevVal.setMainfunName(this.linkParent.mainFunName).setRowID(
            this.linkParent.rowID
          );
          Tsrv.getDefaultVal(TdevVal)
            .then(fvs => {
              fvs.forEach(fv => {
                if (fields.has(fv.field)) {
                  row[fv.field] = fv.value;
                }
              });
            })
            .catch(r => {
              throw new Error(r);
            });

          let sort: number = 0;
          const currentRows = this.GT_editor.getGrid().getTableData().fullData;
          if (
            Object.prototype.toString.call(index) === '[object Object]' &&
            !Tsrv.noValue(index)
          ) {
            const _sort_ = index['_sort_'];
            if (Number.isInteger(_sort_)) {
              const between = currentRows.filter(
                el => el['_sort_'] < _sort_ && el['_sort_'] > _sort_ - 1
              );
              // 插入到指定行
              if (between.length === 0) {
                sort = ((_sort_ - 1) * 100 + 1) / 100;
                row['_sort_'] = sort;
              } else {
                between.push(row);
                // 整理排序_sort_
                this.adjustRowSort(between, _sort_ - 1);
              }
            } else if (Tsrv.utils.isNumber(_sort_)) {
              //
              const s = Math.floor(_sort_);
              const between = currentRows.filter(
                el =>
                  !Tsrv.noValue(el['_sort_']) &&
                  el['_sort_'] > s &&
                  el['_sort_'] < s + 1
              );
              const coordinate = (_sort_ - s) * 100;
              between.splice(coordinate - 1, 0, row);
              this.adjustRowSort(between, s);
            }
          }
          // 如果是插入到第一行，则排序为第一行的排序减去0.000001
          if (index === null) {
            const data = Tsrv.utils.clone(currentRows[1], true);
            const firstSort = data['_sort_'];
            sort = (firstSort * 100 - 1) / 100;
            Tsrv.utils.isNumber(sort) && (row['_sort_'] = sort);
          }
          // 排序
          // this.GT_editor.updateSortNum(index);
          this.updateSaveBtnStatus();
        });
    }
    this.editStatus = true;
  }

  private adjustRowSort(rows: Array<any>, coordinate: number) {
    const fullData = this.GT_editor.getGrid().getTableData().fullData;
    for (let i = 0; i < rows.length; i++) {
      const el = rows[i];
      el['_sort_'] = coordinate + (i + 1) / 100;
      const findRow = Tsrv.utils.find(fullData, item => {
        // return item['_XID'] === el['_XID'];
        return item['id'] === el['id'];
      });
      findRow['_sort_'] = el['_sort_'];
    }
  }

  /**
   * clearTableData 清除表数据
   */
  public clearTableData(options?: { resetM2O?: boolean; resetSLC?: boolean }) {
    return new Promise(resolve => {
      // 重置翻页和排序
      if (this.pagerConfig) {
        this.pagerConfig.total = 0;
      }
      this.seqStartIndex = 0;
      this.tablePage.currentPage = 1;

      // 重置数据
      this.cloudData = [];
      this.localData = [];

      // 重置m2o和下拉
      if (options) {
        if (options.resetM2O === true) {
          Tsrv.utils.clear(this.m2oSetting, null);
        }
        if (options.resetSLC === true) {
          Tsrv.utils.clear(this.slcSetting, null);
        }
      }
      resolve(true);
    });
  }

  // 临时删除
  public remove() {
    if (!this.isLoadEditLock && this.isUseEditLock) {
      this.GT_editor.loadEditLock().then(b => {
        this.isLoadEditLock = b; // 取编辑锁的结果
        if (!b) {
          this.$msg(Tsrv.getI18nByValue('获取编辑锁失败'));
        } else {
          this.removeEditLockChk();
        }
      });
    } else {
      this.removeEditLockChk();
    }
  }

  // 永久删除
  public delete() {
    if (!this.isLoadEditLock && this.isUseEditLock) {
      this.GT_editor.loadEditLock().then(b => {
        this.isLoadEditLock = b; // 取编辑锁的结果
        if (!b) {
          this.$msg(Tsrv.getI18nByValue('获取编辑锁失败'));
        } else {
          this.delEditLockChk();
        }
      });
    } else {
      this.delEditLockChk();
    }
  }

  private removeEditLockChk() {
    const removes = this.GT_editor.getGrid()
      .getCheckboxRecords()
      .map(el => {
        return el.id;
      });
    // if (removes.length > 0) {
    //   for (const id of removes) {
    //     if (this.GT_editor.editLocked.has(id)) {
    //       this.$msg('214,FE,11,Data locked');
    //       return;
    //     }
    //   }
    // }
    this.$Modal.confirm({
      title: Tsrv.getI18nByPath('prompt.isDeleteTemData') as string,
      content: Tsrv.getI18nByPath('prompt.deleteTemData') as string,
      onOk: () => {
        this.removeSelected();
      }
    });
  }

  private delEditLockChk() {
    const removes = this.GT_editor.getGrid()
      .getCheckboxRecords()
      .map(el => {
        return el.id;
      });
    if (removes.length > 0) {
      for (const id of removes) {
        if (this.GT_editor.editLocked.has(id)) {
          this.$msg('214,FE,11,Data locked');
          return;
        }
      }
    }
    this.$Modal.confirm({
      title: Tsrv.getI18nByPath('prompt.isDeleteData') as string,
      content: Tsrv.getI18nByPath('prompt.deleteData') as string,
      onOk: () => {
        this.GT_editor.beforeDelete();
      }
    });
  }

  /**
   * @Author: ssj
   * @param {*}
   * @return {*}
   * @description: 导入
   */
  public import() {
    Tsrv.utils
      .createModal('o-import-panel', {
        funName: this.GT_editor.getFunName(),
        // modalSize: [385, 335]
        modalSize: [385, 150]
      })
      .then(data => {
        this.commitEvent('reload');
      });
  }

  /**
   * 设置表尾数据
   */
  public setFooterData(data: { [key: string]: string }) {
    for (const key in data) {
      this.footerData[key] = data[key];
    }
  }

  public async doPasteColunm(field: string) {
    // this.copyColunm.toField = field;
    // const params: any = {
    //   funcName: this.GT_editor.getFunName(),
    //   tableName: this.GT_editor.getTableName(),
    //   parentID: this.linkParent.rowID || 0,
    //   parentFuncName: this.linkParent.mainFunName || '',
    //   scField: this.copyColunm.fromField,
    //   destField: field
    // };
    // const { data } = await Tsrv.httpReqV1.fun('_sys_p_coldata_copy', params);
    // if (data.success) {
    //   this.$msg(data.msg);
    //   this.GT_editor.loadTableData();
    // } else {
    //   this.$msg(data.msg);
    // }
  }

  /**
   * setToolbarStatus 设置toolbar的状态
   */
  public setToolbarStatus(name: string, key: string, value: boolean) {
    if (vxeConfig.setLevelParams(this.toolbar, name, key, value))
      this.updateContextMenu();
  }

  /**
   * @Author: ssj
   * @param {value} value  修改状态
   * @description: 编辑表格
   */

  public editTable(value: boolean) {
    this.setModify(value);
    if (value) {
      this.GT_editor.sendEventCoordination('edit');
      this.editStatus = true;
      if (this.isUseEditLock) {
        this.GT_editor.loadEditLock().then(b => {
          this.isLoadEditLock = b; // 取编辑锁的结果
          if (!b) {
            this.$msg(Tsrv.getI18nByValue('获取编辑锁失败'));
          }
        });
      }
    } else {
      this.GT_editor.sendEventCoordination('unEdit');
      !this.getChanges().updateRecords.length && (this.editStatus = false);
    }
    // 取消编辑还原数据
    if (!value) {
      this.GT_editor.getGrid().revertData();
      this.updateSaveBtnStatus();
      this.toolbar.delete.isDisable = true;
      this.GT_editor.unLockALL();
    }
  }

  /**
   * setModify 切换修改状态
   */
  public setModify(value: boolean) {
    if (this.toolbar) {
      // this.GT_editor.getGrid().clearActived();
      this.GT_editor.getGrid().clearEdit();
      this.isEditable = value;
      if (!this.isEditable) {
        this.GT_editor.editorStatus = 'none';
      }

      this.GT_editor.getGrid().reloadRow({});
      this.updateContextMenu();
    }
  }

  /**
   * 更新右键功能
   */
  public updateContextMenu() {
    this.contextMenu = this.getContext();
    this.contextMenu['enabled'] = true;
    this.contextMenu['visibleMethod'] = this.isEnabledContextMenu;
  }

  public isEnabledContextMenu(e): boolean {
    return true;
  }

  /**
   * setColumnVisible 设置列的可见
   */
  public setColumnVisible(property: string, value: boolean) {
    vxeConfig.grid.setColumnVisible(
      this.GT_editor.getGrid(),
      this.tableColumns,
      property,
      value
    );
  }

  public setAllColumnInvisible() {
    if (!Tsrv.noValue(this.tableColumns)) {
      this.tableColumns.forEach((el: any) => {
        if (!Tsrv.noValue(el?.field)) {
          let field = el.field;
          if (field.indexOf('|') > -1 && field.split('|').length > 1) {
            field = field.split('|')[1];
          }
          this.setColumnVisible(field, false);
        }
      });
    }
  }

  /**
   * 获取数据集
   */
  public getChanges(type?: string): any {
    return vxeConfig.grid.getChanges(
      this.GT_editor.getGrid(),
      this.cloudData,
      this.subQueryArr,
      type
    );
  }

  /**
   * 设置数据源
   */
  public setDataSource(source: string, name?: string) {
    this.dataSource = source;
    if (source === 'table') {
      this.GT_editor.setTableName(name || '');
    }
  }

  /**
   * 设置advq的参数
   */
  public setAdvqParams(params: any) {
    this.advqParams = params;
  }

  private footerMethod(ev: any) {
    return vxeConfig.grid.footerMethod(
      ev,
      this.isFooterRemote && !this.isBasePanel,
      this.footerData
    );
  }

  /**
   * 跳转到某一页
   */
  public jumpTo(to: number | null) {
    if (to === -1) {
      this.tablePage.currentPage--;
    } else if (to === null) {
      this.tablePage.currentPage++;
    } else {
      this.tablePage.currentPage = to;
    }
    this.GT_editor.loadTableData();
  }

  /**
   * 设置页面大小
   */
  public setPageSize(size: number) {
    this.tablePage.pageSize = size;
    this.GT_editor.loadTableData();
  }

  /**
   * 设置style
   */
  public setStyle(style: any) {
    this.tableStyle = style;
    this.pagerConfig = style.showPager ? this.tablePage : false;
    // this.defaultToolbar = style.showToolbar
    //   ? this.toolbar.default.isShow
    //     ? this.defaultToolbar
    //     : {}
    //   : false;
    if (!style.showToolbar) {
      this.defaultToolbar['enabled'] = false;
    }
  }

  /**
   * 设置localdata
   */
  // public setData(data: any) {
  //   data = Tsrv.utils.clone(data, true);
  //   data.forEach((el, idx) => {
  //     el._XID = `row_${ idx }`;
  //   });
  //   this.localData = data;
  //   this.seqStartIndex = 0;
  // }

  /**
   * 设置datasetting
   */
  public setDataSetting(setting: any, key?: any) {
    if (key) {
      this.tableDataSetting[key] = setting;
    } else {
      this.tableDataSetting = setting;
    }

    this.isFooterRemote =
      this.tableDataSetting.isFooterRemote === undefined
        ? true
        : this.tableDataSetting.isFooterRemote;
  }

  private replaceSensitive(value) {
    if (typeof value === 'string') {
      return (
        value
          .replace(/,/g, '\\,')
          .replace(/:/g, '\\:')
          // .replace(/\|/g, "\\|")
          .replace(/\*/g, '\\*')
      );
    }
    return value;
  }

  /**
   * 筛选方法
   */
  private filterChange(e: any) {
    this.GT_editor.filterChange(e);
    this.seqStartIndex = 0;
    this.tablePage.currentPage = 1;
    this.GT_editor.loadTableData();
  }

  /**
   * @Author: wiz
   * @param {*}
   * @return {*}
   * @description: 返回高亮行数据
   */
  public getSelectRowRecord() {
    return Tsrv.utils.clone(this.GT_editor.getGrid().getCurrentRecord(), true);
  }

  exportMethod(options) {
    this.GT_editor.exportMethod(options); // e.options
  }

  public getDbType(): string {
    return this.GT_editor.getDbType();
  }

  public loadDataInfo(e) {
    this.$emit('load-data-info', e);
  }

  cleanSubCompData(p: N_oSetupPanel.N_comps.T_eventCoordinationToolbar) {}

  private reframe(el: HTMLElement) {
    this.gridEl['style'].setProperty(
      `--vxe-toolbar--custom-body-maxheight`,
      `${this.getElHeight(el) / 2 - 100}px`
    );
  }

  /**
   * GridBody右键监听事件
   */
  private listenGridBody() {
    const gridBodyEl = document.querySelector('.vxe-table--body-wrapper');
    if (!Tsrv.noValue(gridBodyEl)) {
      gridBodyEl.addEventListener('contextmenu', this.listenContextMenu);
    }
  }

  /**
   * vxe-grid 右键菜单 鼠标离开事件监听
   */
  private listenContextMenu() {
    // 给 girdBody 右键菜单 添加 监听事件
    setTimeout(() => {
      // 当频繁点击右键打开 右键菜单时 处理
      if (!Tsrv.noValue(this.contextMenuEl)) {
        this.contextMenuEl.removeEventListener(
          'mouseleave',
          this.menuMouseleaveListenCallback
        );
        this.contextMenuEl = null;
      }
      // 主要
      this.contextMenuEl = document.querySelector(
        '.vxe-table--context-menu-wrapper'
      );
      if (!Tsrv.noValue(this.contextMenuEl)) {
        this.contextMenuEl.addEventListener(
          'mouseleave',
          this.menuMouseleaveListenCallback
        );
      }
    }, 0);
  }

  private menuMouseleaveListenCallback() {
    if (Tsrv.noValue(this.contextMenuEl)) {
      return;
    }
    this.contextMenuEl.removeEventListener(
      'mouseleave',
      this.menuMouseleaveListenCallback
    );
    this.GT_editor.getGrid().closeMenu();
  }

  public getElHeight(el: any) {
    return Tsrv.utils.sum(el.children, (e: any) => e.offsetHeight);
  }

  /**
   * @description: 执行功能的自定义事件
   * @return {*}
   * @author: swc
   * @Date: 2024-05-30 18:27:09
   * @LastEditors: swc
   * @LastEditTime: Do not edit
   */
  private async handleActions(pubApi: string, from: string) {
    const params = this.GT_editor.getSelectedData('select');
    params.title = pubApi;
    params.from = from;
    return await this.GT_editor.doEvent(pubApi, params);
  }

  private reload(): Promise<boolean> {
    return new Promise((resolve, reject) => {
      this.GT_editor.sendEventCoordination('refresh');
      this.GT_editor.editorStatus = 'none';
      this.GT_editor.loadTableData()
        .then(res => {
          this.GT_editor.callControlEvent('refresh');
          res && (this.editStatus = false);
          resolve(true);
        })
        .catch(_ => reject(false));
      this.GT_editor.unLockALL(); // 解锁
    });
  }

  /**
   * 切换basegrid展示模式————table-or-graph
   * @param
   */
  public switchModel() {
    // 切换前检查————（没有编号1、无法排版 或者 2、不参与排版）
    const isCanSwitch = Tsrv.getx(this.config, 'tableGraphMode', false);
    const pIdFind = this._config.tableColumns.find(
      e => e?.field === Tsrv.lexicon.globalVar.fieldName.parentId
    );
    if (isCanSwitch && !Tsrv.noValue(pIdFind)) {
      this.displayModel = !this.displayModel;
      // （渲染问题修改成功，此处可删除）
      const flowchart = this.GT_compBox.getCompMergeName(
        this.G_compID,
        'girdFlowchart'
      );
      setTimeout(() => {
        flowchart.cFlowchart.graph.zoomToFit({
          padding: 20,
          preserveAspectRatio: true
        });
      }, 100);
    } else {
      isCanSwitch &&
        Tsrv.noValue(pIdFind) &&
        this.$Message.warning('当前表格缺少"p_id"字段，不支持切换模式');
    }
  }

  /**
   * 初始化表格状态
   */
  public initTableStatus() {
    this.GT_editor.getGrid().revertData();
    this.GT_editor.getGrid().clearCheckboxRow();
    this.checkboxChange(null);
    this.updateSaveBtnStatus();
    this.toolbar.delete.isDisable = true;
    this.setToolbarStatus('edit', 'value', false);
    this.setToolbarStatus('edit', 'isDisable', false);
    this.editStatus = false;
    this.setModify(false);
    this.GT_editor.sendEventCoordination('refresh');
    this.GT_editor.unLockALL();
  }
}
</script>

<style scoped lang="scss">
.wy-grid ::v-deep {
  height: 100%;
  overflow: hidden;
  border: 1px solid var(--default-border-color);
  border-radius: 2px;
}
.wy-grid ::v-deep .vxe-toolbar.size--mini {
  padding: 0;
  background-color: var(--basegrid-toolbar-bg-color);
}
.top-card-box {
  position: relative;
  display: flex;
  justify-content: center; /* 水平居中 */
  .top-card-box-title {
    display: flex;
    justify-content: center; /* 水平居中 */
  }
}
.search-box ::v-deep {
  height: 100%;
  overflow: hidden;
  .wy-grid {
    height: 100%;
    overflow-x: hidden;
    overflow-y: auto;
  }
}
.wy-grid-cover {
  height: 100%;
  // 分割线显示与隐藏
  ::v-deep .ivu-split-wrapper {
    .ivu-split-trigger-con {
      display: var(--splitTrigger);
    }
  }
}
.search-footer {
  margin-left: 10px;
}
.charts {
  overflow-x: hidden;
  overflow-y: auto;
  height: 100%;
  .chart-group {
    height: 100%;
    border-bottom: 3px solid #f1f1f1;
    .chart-cover {
      height: 100%;
      position: relative;

      .chart-toolbar {
        display: none;
        position: absolute;
        top: 20px;
        left: 20px;
        .ivu-icon {
          font-size: 16px;
          cursor: pointer;
        }
      }
      &:hover {
        .chart-toolbar {
          display: block;
        }
      }
    }
    .chart-expand {
      position: fixed;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      z-index: 1000;
    }
    .chart-shape {
      height: 100%;
      width: 100%;
      padding: 20px 10px;
      background-color: #fff;
    }
  }
}
.grid-content {
  width: 100%;
  height: 100%;
  // display: flex;
  // flex-direction: column;
  overflow: hidden;

  ::v-deep .vxe-toolbar {
    .vxe-custom--option-wrapper {
      .vxe-custom--body {
        max-height: var(--vxe-toolbar--custom-body-maxheight);
      }
    }
  }
}
.grid-query {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}
</style>
